从 XOML 动态加载工作流活动
我正在尝试实现一个类似于 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在这里实现您的目标可能非常棘手,但是让我们从简单的开始: -
您可以使用
System.Workflow.ComponentModel.Serialization< 中找到的
WorkflowMarkupSerializer
从 XOML 重建工作流程/代码> 命名空间。同样,您可以使用 CompostiteActivityMarkupSerializer 重建继承自 CompositeActivity 的活动的“片段”。
然而,要将新的根活动集成到当前运行的工作流程中需要更多的工作。您需要使用
WorkflowChanges
类的实例通过修改当前实例使用的工作流定义来创建新活动。现在的文档在这个主题上有些粗略,甚至有点回避。不过,可以收集到两个重要的点: -
ApplyWorkflowChanges
并且此成员具有protected
可访问性。因此,我们可以推断我们将需要一个自定义根活动来至少帮助满足此要求。
可能有更多的方法可以构建这种结构,但假设我们有一个 SequenceActivity,其中有一个执行工作流修改的自定义“InvokeWorkflow”活动,并且我们打算将生成的新活动放在最后这个包含序列。
首先,我们需要一个可以在自定义根活动上实现的接口定义:-
在自定义根活动中,我们将显式实现此接口:-
在自定义“InvokeWorkflow”活动的
Execute
方法中:-注意我还没有实际测试过这些,它是由埋在文档中的信息碎片拼凑而成的。
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 theSystem.Workflow.ComponentModel.Serialization
namespace.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:-
ApplyWorkflowChanges
is needed and this member hasprotected
accessibility.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:-
In our custom root activity we would implement this interface explicitly:-
In the
Execute
method of the custom "InvokeWorkflow" activity:-Note I haven't actually tested any of this, its cobbled together from crumbs of info buried in the documentation.
非常感谢安东尼。
不得不说,你的动态工作流程修改很酷,但是有点吓人。我最终使用 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