在工作流程4 RC中指定的活动
所以我有这个要求来启动在运行时提供给我的活动。 为了促进这一点,我建立了一个WorkflowService,它接收Xaml的活动,对它们进行水合并将它们踢出去。
听起来很简单...
...这是我在Xaml中的WorkflowService
<Activity
x:Class="Workflow.Services.WorkflowService.WorkflowService"
...
xmlns:local1="clr-namespace:Workflow.Activities" >
<Sequence sap:VirtualizedContainerService.HintSize="277,272">
<Sequence.Variables>
<Variable x:TypeArguments="local:Workflow" Name="Workflow" />
</Sequence.Variables>
<sap:WorkflowViewStateService.ViewState>
<scg3:Dictionary x:TypeArguments="x:String, x:Object">
<x:Boolean x:Key="IsExpanded">True</x:Boolean>
</scg3:Dictionary>
</sap:WorkflowViewStateService.ViewState>
<p:Receive CanCreateInstance="True" DisplayName="ReceiveSubmitWorkflow" sap:VirtualizedContainerService.HintSize="255,86" OperationName="SubmitWorkflow" ServiceContractName="IWorkflowService">
<p:ReceiveParametersContent>
<OutArgument x:TypeArguments="local:Workflow" x:Key="workflow">[Workflow]</OutArgument>
</p:ReceiveParametersContent>
</p:Receive>
<local1:InvokeActivity Activity="[ActivityXamlServices.Load(New System.IO.StringReader(Workflow.Xaml))]" sap:VirtualizedContainerService.HintSize="255,22" />
</Sequence>
</Activity>
......除了重复使用“工作流程”之外,它非常简单。 事实上,它只是一个Sequence
具有Receive
和[当前]自定义活动称为InvokeActivity
。 稍微了解一下。
Receive
活动接受自定义类型,
[DataContract]
public class Workflow
{
[DataMember]
public string Xaml { get; set; }
}
其中包含一个字符串,其内容将被解释为Xaml。 您可以看到VB表达式,然后将该Xaml转换为一个活动并将其传递。
现在这第二个位,自定义InvokeActivity
是我有问题的地方。
第一个问题:
1)给定一个任意的任务,在运行时提供[如上所述]是否可以使用WF4RC随附的活动启动此活动,开箱即用? 我是相当新的,并认为我通过API和现有文档做了很好的工作,但也可以问:)
第二:
2)我第一次尝试实现一个自定义的InvokeActivity
看起来像这样
public sealed class InvokeActivity : NativeActivity
{
private static readonly ILog _log =
LogManager.GetLogger (typeof (InvokeActivity));
public InArgument<Activity> Activity { get; set; }
public InvokeActivity ()
{
_log.DebugFormat ("Instantiated.");
}
protected override void Execute (NativeActivityContext context)
{
Activity activity = Activity.Get (context);
_log.DebugFormat ("Scheduling activity [{0}]...", activity.DisplayName);
// throws exception to lack of metadata! :(
ActivityInstance instance =
context.ScheduleActivity (activity, OnComplete, OnFault);
_log.DebugFormat (
"Scheduled activity [{0}] with instance id [{1}].",
activity.DisplayName,
instance.Id);
}
protected override void CacheMetadata (NativeActivityMetadata metadata)
{
// how does one add InArgument<T> to metadata? not easily
// is my first guess
base.CacheMetadata (metadata);
}
// private methods
private void OnComplete (
NativeActivityContext context,
ActivityInstance instance)
{
_log.DebugFormat (
"Scheduled activity [{0}] with instance id [{1}] has [{2}].",
instance.Activity.DisplayName,
instance.Id,
instance.State);
}
private void OnFault (
NativeActivityFaultContext context,
Exception exception,
ActivityInstance instance)
{
_log.ErrorFormat (
@"Scheduled activity [{0}] with instance id [{1}] has faulted in state [{2}]
{3}",
instance.Activity.DisplayName,
instance.Id,
instance.State,
exception.ToStringFullStackTrace ());
}
}
哪些尝试在当前上下文中安排指定的活动。 不幸的是,这失败了。 当我尝试安排所述活动时,运行时将返回以下例外
提供的活动在处理其元数据时不属于此工作流定义的一部分。 名为“DynamicActivity”的问题活动由名为“InvokeActivity”的活动提供。
对,所以在运行时提供的“动态”活动不是InvokeActivity
元数据的成员。 谷歌搜索,并遇到这一点。 无法理清如何为元数据缓存指定InArgument<Activity>
,所以我的第二个问题自然就是如何解决这个问题? 以这种方式建议使用context.ScheduleActivity (...)
吗?
第三次也是最后,
3)我暂时已经解决了这个[更简单]的解决方案,
public sealed class InvokeActivity : NativeActivity
{
private static readonly ILog _log =
LogManager.GetLogger (typeof (InvokeActivity));
public InArgument<Activity> Activity { get; set; }
public InvokeActivity ()
{
_log.DebugFormat ("Instantiated.");
}
protected override void Execute (NativeActivityContext context)
{
Activity activity = Activity.Get (context);
_log.DebugFormat ("Invoking activity [{0}] ...", activity.DisplayName);
// synchronous execution ... a little less than ideal, this
// seems heavy handed, and not entirely semantic-equivalent
// to what i want. i really want to invoke this runtime
// activity as if it were one of my own, not a separate
// process - wrong mentality?
WorkflowInvoker.Invoke (activity);
_log.DebugFormat ("Invoked activity [{0}].", activity.DisplayName);
}
}
它只是在自己的运行时实例中同步调用指定的任务thingy [使用WF4白话当然是有问题的]。 最后,我想挖掘WF的跟踪和可能的持久性设施。 所以我的第三个也是最后一个问题是,就我想要做的事情而言(即从客户端应用程序启动任意工作流入口),这是首选方法吗?
好的,先谢谢你的时间和考虑:)
在处理其元数据时,提供的活动不属于此工作流定义的一部分。 名为“DynamicActivity”的问题活动由名为“InvokeActivity”的活动提供。
工作流程4.0只允许您在开始执行之前安排属于树的子项。
这个规则可能存在,因为这样构建的树可以被多个工作实例重用。 如果实例A在实例B仍在运行时修改树,则结果会给运行团队带来可怕的麻烦。
实际上,这意味着您可以在运行时动态调度子进程所需的唯一方法是启动全新的工作流程(并可选择等待完成)。
链接地址: http://www.djcxy.com/p/95869.html