Workflow 从XOML动态加载工作流活动

Workflow 从XOML动态加载工作流活动,workflow,workflow-foundation,workflow-activity,Workflow,Workflow Foundation,Workflow Activity,我正在尝试实现一个类似于InvokeWorkflow的活动,它可以动态加载一个XOML文件,从中实例化一个活动树,并将其用作其唯一的子级 这与InvokeWorkflow类似,不同之处在于动态加载的活动被内联到主工作流中(从监控的角度来看这更好) 我将XamlReader视为实现这一点的一种潜在方法,但显然它不适合加载工作流(仅限于UI内容) 谢谢, 朱利安在这里实现你的目标可能相当棘手,但是让我们从简单的一点开始:- 您可以使用System.workflow.ComponentModel.Se

我正在尝试实现一个类似于InvokeWorkflow的活动,它可以动态加载一个XOML文件,从中实例化一个活动树,并将其用作其唯一的子级

这与InvokeWorkflow类似,不同之处在于动态加载的活动被内联到主工作流中(从监控的角度来看这更好)

我将XamlReader视为实现这一点的一种潜在方法,但显然它不适合加载工作流(仅限于UI内容)

谢谢,
朱利安

在这里实现你的目标可能相当棘手,但是让我们从简单的一点开始:-

您可以使用
System.workflow.ComponentModel.Serialization
命名空间中的
WorkflowMarkupSerializer
从XOML重构工作流

var serializer = new WorkflowMarkupSerializer();
object root = serializer.Deserialize(myXmlReader);
类似地,您可以使用
CompositeActivityMarkupSerializer
重构从CompositeActivity继承而来的东西中包含的活动的“片段”

但是,要将新的根活动集成到当前运行的工作流中,需要做更多的工作。您需要使用
WorkflowChanges
类的实例,通过修改当前实例使用的工作流定义来创建新活动

现在的文档在这个问题上有些粗略,甚至有点含糊不清。不过,我们可以收集到两个要点:

  • 最终需要调用
    ApplyWorkflowChanges
    ,并且该成员具有
    受保护的
    可访问性
  • 文档指出,这需要在工作流的根活动上发生
  • 因此,我们可以推断,我们将需要一个定制的根活动来至少帮助满足这个需求

    可能有更多的方法可以对其进行结构化,但假设我们有一个
    SequenceActivity
    ,其中我们有一个自定义的“InvokeWorkflow”活动来执行工作流修改,并且我们打算将生成的新活动放在这个包含序列的末尾

    首先,我们需要一个可以在自定义根活动上实现的接口定义:-

    internal interface IModifiableWorkflow
    {
         void ApplyWorkflowChanges(WorkflowChanges workflowChanges);
    }
    
    // Get root activity     
    var root = this.Parent;
    while (root.Parent != null) { root = root.Parent; }
    
    // Create an instance of WorkflowChanges based on the root activity
    var changes = new WorkflowChanges(root);
    
    //Find the parent sequence activity in the transient workflow definition
    var target = changes.TransientWorkflow.GetActivityByName(this.Parent.Name);
    
    Activity newActivity = YourCodeToLoadActivityDetailsFromXoml();
    
    target.Activities.Add(newActivity);
    
    //Apply the new changes
    ((IModifiableWorkflow)root).ApplyWorkflowChanges(changes);
    
    在我们的自定义根活动中,我们将显式实现此接口:-

    public class CustomSequentialActivity : SequentialWorkflowActivity, IModifiableWorkflow
    {
        void IModifiableWorkflow.ApplyWorkflowChanges(WorkflowChanges workflowChanges)
        {
            base.ApplyWorkflowChanges(workflowChanges);
        }
    }
    
    在自定义“InvokeWorkflow”活动的
    执行方法中:-

    internal interface IModifiableWorkflow
    {
         void ApplyWorkflowChanges(WorkflowChanges workflowChanges);
    }
    
    // Get root activity     
    var root = this.Parent;
    while (root.Parent != null) { root = root.Parent; }
    
    // Create an instance of WorkflowChanges based on the root activity
    var changes = new WorkflowChanges(root);
    
    //Find the parent sequence activity in the transient workflow definition
    var target = changes.TransientWorkflow.GetActivityByName(this.Parent.Name);
    
    Activity newActivity = YourCodeToLoadActivityDetailsFromXoml();
    
    target.Activities.Add(newActivity);
    
    //Apply the new changes
    ((IModifiableWorkflow)root).ApplyWorkflowChanges(changes);
    

    注意,我实际上还没有测试过这些,它是从文档中隐藏的信息碎片拼凑而成的。

    非常感谢Anthony

    我不得不说,您的动态工作流修改很酷,但有点吓人。最后,我使用了对的修改来编写工作流

    我从运行时加载的仅XOML工作流(使用WF 3.5)中学到的一些技巧:

    • 删除XOML中的x:Class属性

    • 删除代码隐藏文件

    • 为了让VS设计器工作,这些XOML文件需要在它们自己的项目中分开(在XOML所在的项目中没有代码,例如基本活动或公共类型)

    • 将XOML标记为VS中的内容,并始终复制,以便将其与二进制文件放在一起

    • 即使如此,VS2008通常需要完全重建,以便正确复制新修改的XOML文件

    • 如前所述,您可能需要手动设置断点


    链接已断开:(