从 XOML 动态加载工作流活动

发布于 2024-08-11 11:28:38 字数 211 浏览 14 评论 0原文

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

这与 InvokeWorkflow 类似,只不过动态加载的活动内联到主工作流中(从监视角度来看更好)。

我将 XamlReader 视为执行此操作的潜在方法,但显然它不适合加载工作流程(仅限 UI 内容)。

谢谢, 朱利安

I am trying to implement an activity similar to InvokeWorkflow, which could dynamically load a XOML file, instantiate an activity tree from it, and use it as its only child.

This would be similar to InvokeWorkflow except that the activities which are dynamically loaded are inlined into the main workflow (which is better from a monitoring perspective).

I looked at XamlReader as a potential way of doing this, but apparently it is not suitable for loading workflows (only UI stuff).

Thanks,
Julien

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

吹泡泡o 2024-08-18 11:28:39

在这里实现您的目标可能非常棘手,但是让我们从简单的开始: -

您可以使用 System.Workflow.ComponentModel.Serialization< 中找到的 WorkflowMarkupSerializer 从 XOML 重建工作流程/代码> 命名空间。

var serializer = new WorkflowMarkupSerializer();
object root = serializer.Deserialize(myXmlReader);

同样,您可以使用 CompostiteActivityMarkupSerializer 重建继承自 CompositeActivity 的活动的“片段”。

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

现在的文档在这个主题上有些粗略,甚至有点回避。不过,可以收集到两个重要的点: -

  1. 最终需要调用 ApplyWorkflowChanges 并且此成员具有 protected 可访问性。
  2. 文档表明这需要在工作流的根活动上发生。

因此,我们可以推断我们将需要一个自定义根活动来至少帮助满足此要求。

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

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

internal interface IModifiableWorkflow
{
     void ApplyWorkflowChanges(WorkflowChanges workflowChanges);
}

在自定义根活动中,我们将显式实现此接口:-

public class CustomSequentialActivity : SequentialWorkflowActivity, IModifiableWorkflow
{
    void IModifiableWorkflow.ApplyWorkflowChanges(WorkflowChanges workflowChanges)
    {
        base.ApplyWorkflowChanges(workflowChanges);
    }
}

在自定义“InvokeWorkflow”活动的 Execute 方法中:-

// 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);

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

Achieving your goal here is likely to be quite tricky however lets start with the easy bit:-

You can reconstruct a workflow from XOML using the WorkflowMarkupSerializer found in the System.Workflow.ComponentModel.Serialization namespace.

var serializer = new WorkflowMarkupSerializer();
object root = serializer.Deserialize(myXmlReader);

Similarly you could reconstruct a "snippet" of activities held in something that inherits from CompositeActivity using the CompostiteActivityMarkupSerializer.

However, to integrate the new root activity into the currently running workflow requires more work. You need to use an instance of the WorkflowChanges class to make the new activity by modifing the Workflow definition used by the current instance.

Now the documentation is some what sketchy and even a little evasive on this subject. Two important points can be gleaned though:-

  1. Ultimately a call to ApplyWorkflowChanges is needed and this member has protected accessibility.
  2. The documentation indicates that this needs to occur on the root activity of a workflow.

Hence we can deduce that we will need a custom root activity to at least assist in this requirement.

There are probably more ways that this could be structured but lets assume we have a SequenceActivity in which we have a custom "InvokeWorkflow" activity performing the workflow modification and we intend to place the resulting new activity at the end this containing sequence.

First we'll need an interface definition which we can implement on the custom root activity:-

internal interface IModifiableWorkflow
{
     void ApplyWorkflowChanges(WorkflowChanges workflowChanges);
}

In our custom root activity we would implement this interface explicitly:-

public class CustomSequentialActivity : SequentialWorkflowActivity, IModifiableWorkflow
{
    void IModifiableWorkflow.ApplyWorkflowChanges(WorkflowChanges workflowChanges)
    {
        base.ApplyWorkflowChanges(workflowChanges);
    }
}

In the Execute method of the custom "InvokeWorkflow" activity:-

// 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);

Note I haven't actually tested any of this, its cobbled together from crumbs of info buried in the documentation.

凉薄对峙 2024-08-18 11:28:39

非常感谢安东尼。

不得不说,你的动态工作流程修改很酷,但是有点吓人。我最终使用 Jon Flander 的 CallWorkflowActivity

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

  • 删除 XOML 内的 x:Class 属性

  • 删除代码隐藏文件

  • 为了让 VS 设计器正常工作,这些 XOML 文件需要在各自的项目中分开(XOML 所在的项目中没有代码,例如基本活动或常见类型)位于)

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

  • 即便如此,VS 2008 通常需要在为了正确复制新修改的 XOML 文件...

  • 您可能需要手动设置断点,如所解释的此处

Thanks so much Anthony.

I have to say that your dynamic workflow modification is cool, but it was a little scary. I ended up composing workflows using a modification of Jon Flander's CallWorkflowActivity.

Some tricks I learned with XOML-only workflows loaded at runtime (using WF 3.5):

  • remove x:Class attribute inside the XOML

  • delete the code-behind file

  • for the VS designer to work, those XOML files need to be separated in their own projects (no code, such as base activities or common types, in the project where the XOML is located)

  • mark the XOML as Content in VS and Copy Always so it is placed with your binaries

  • even so, VS 2008 usually needs a full Rebuild in order to properly copy newly modified XOML files...

  • you may need to set breakpoints manually, as explained here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文