Dependency injection 使用IoC编写工作流

Dependency injection 使用IoC编写工作流,dependency-injection,workflow,inversion-of-control,mef,workflow-foundation,Dependency Injection,Workflow,Inversion Of Control,Mef,Workflow Foundation,我正在构建一个WPF应用程序,它使用IoC容器进行依赖注入(在我的例子中是MEF)。该应用程序包含几个详细的流程,我们将这些流程建模为WF工作流。但是,一些(不是全部)活动依赖于由IoC容器管理的服务和其他组件。我看到了一些可能的方法来实现这一点,但它们似乎都没有遵循最佳实践。它们是: 在每个活动的构造函数或执行方法中使用服务定位器来定位 并设置依赖项。就个人而言,我不喜欢服务定位器,因为我认为它们违反了DI的一个租户,而代码不知道依赖关系是在哪里或如何创建的。它还降低了活动的可测试性(或者至少

我正在构建一个WPF应用程序,它使用IoC容器进行依赖注入(在我的例子中是MEF)。该应用程序包含几个详细的流程,我们将这些流程建模为WF工作流。但是,一些(不是全部)活动依赖于由IoC容器管理的服务和其他组件。我看到了一些可能的方法来实现这一点,但它们似乎都没有遵循最佳实践。它们是:

  • 在每个活动的构造函数或执行方法中使用服务定位器来定位 并设置依赖项。就个人而言,我不喜欢服务定位器,因为我认为它们违反了DI的一个租户,而代码不知道依赖关系是在哪里或如何创建的。它还降低了活动的可测试性(或者至少在测试过程中添加了几个步骤)。我在StackOverflow和CodePlex上看到了一些使用WF服务扩展的示例,它们的工作方式基本相同。我没有使用WF服务,所以这不是一个选项
  • 导出每个活动并让工作流导入它们。 这将确保容器满足所有要求 依赖关系,但这意味着我们没有构建 XAML中的工作流
  • 导出工作流并让其导入所需的依赖项 这些活动。然后我必须将依赖项设置为 要使用的活动的参数。不仅如此 在工作流中有很多开销代码,但现在这意味着 工作流需要了解所有项目的依赖关系 活动。如果某个活动发生更改、被添加或删除,我现在有 对工作流进行更改以适应对工作流的任何更改 依赖关系
  • 采用与#3相同的方法,但不导出 工作流,具有导出的控制类,导入所有 选择依赖项并将其设置为工作流的输入参数 它本身每个活动都会提取它需要的依赖项。这 具有与#3相同的所有问题,需要维护更多代码
  • 那么,我的问题是,我应该采取什么方法?(即,你采取了什么方法?)

    我还假设上面的列表并不全面,希望有人能提出更好的选择,如果有的话


    谢谢

    方法二似乎最合适。您可以在xaml中使用一些活动声明,稍后将使用这些声明导入真实的活动声明

    编辑:

    
    
    然后你可以在这些台词中找到一些东西

    接口IActivityInfo
    {
    IActivity ImportActivity();
    }
    接口IActivityInfo:IActivityInfo
    {
    IActivityInfo信息{get;}
    }
    类传递:IActivityInfo
    {   
    public IActivity ImportActivity(){return ServiceLocator.Current.GetInstance();}
    }
    [导出(类型(活动))]
    类传递活动:IActivity
    {
    }
    

    这种方法可以让您轻松地将xaml设计过程与底层活动分开。

    方法二似乎最合适。您可以在xaml中使用一些活动声明,稍后将使用这些声明导入真实的活动声明

    编辑:

    
    
    然后你可以在这些台词中找到一些东西

    接口IActivityInfo
    {
    IActivity ImportActivity();
    }
    接口IActivityInfo:IActivityInfo
    {
    IActivityInfo信息{get;}
    }
    类传递:IActivityInfo
    {   
    public IActivity ImportActivity(){return ServiceLocator.Current.GetInstance();}
    }
    [导出(类型(活动))]
    类传递活动:IActivity
    {
    }
    

    这种方法可以让您轻松地将xaml设计过程与底层活动分开。

    请详细说明第二句话。因此,最终您将返回到使用服务定位器模式来解决活动。在您的例子中,如果我理解的话,您刚刚创建了一个包装器,可以插入XAML来抽象定位器。您没有显示的是,PassThrough和PassThroughActivity都必须子类化活动(或另一个活动子类型),并且PassThrough必须实现所有方法并委托给“导入的”PassThroughActivity。这需要维护大量代码,特别是当解决方案中有几十个自定义活动需要此行为时。ActivityInfo只需要保存正确初始化活动实例所需的信息。在本例中,我没有使用定位器xaml抽象。。。ActivityInfo不是一个活动,(它是一种生成器模式)。它只需要保存足够的信息就可以正确初始化活动实例。ServiceLocator用于在方法调用期间解析依赖关系(此时不是真正的依赖关系…),而不是在xaml中的ActivityInfo初始化期间解析依赖关系(这可能发生得更早)。所以在xaml中,我得到了ActivityInfo。当需要从中生成真正的工作流时,我称之为导入。是 啊我在工作中遇到过这样的麻烦。我很好奇你是否真的实现了这一点,或者这只是理论上的?我仍然看不到直通是如何不是活动的子类。为了使代码作为工作流的一部分运行,它必须符合工作流运行时(活动)所期望的约定。例如,谁调用ImportActivity,何时调用它?WF希望在活动运行时调用Execute(…),如果PassThrough不是活动的子类,那么模型中的Execute在哪里?请详细说明您的第二句话。因此,最终您将返回到使用服务定位器模式来解析活动。在您的例子中,如果我理解的话,您刚刚创建了一个包装器,可以插入XAML来抽象定位器。您没有显示的是,PassThrough和PassThroughActivity都必须子类化活动(或另一个活动子类型),并且PassThrough必须实现所有方法并委托给“导入的”PassThroughActivity。这需要维护很多代码,特别是当有
    <wf:Workflow.Activities></activities:PassThrough UserId="mstewart"></wf:Workflow.Activities>
    
    interface IActivityInfo
    {
      IActivity ImportActivity();
    }
    interface IActivity<TActivityInfo> where TActivityInfo : IActivityInfo
    {
      IActivityInfo Info { get; }
    }
    
    class PassThrough : IActivityInfo
    {   
      public IActivity ImportActivity(){ return ServiceLocator.Current.GetInstance<IActivity<PassThrough>>(); }
    }
    
    [Export(typeof(IActivity<PassThrough>))]
    class PassThroughActivity : IActivity<PassThrough>
    {
    }