阅读本文后:
我已经按如下方式定义了ForEachFactory:
public class ForEachFactory<T> : IActivityTemplateFactory
{
public Activity Create(DependencyObject target)
{
return new ForEach<T>
{
DisplayName = "ForEachFromFactory",
Body = new ActivityAction<T>
{
Argument = new DelegateInArgument<T>("item")
}
};
}
}
一切正常,但是有可能检查我的案例中的DelegeateInArgument如何命名&#34; item&#34;改变它的价值? 所以如果我在变量部分定义了一个数组并用 {1,2,3}我需要一种方法来检查&#34;项目&#34;取值1,2和3。
为了更准确,我已添加了这张照片,并在foreach内的WriteLine活动中添加了一个断点。当执行将在那里停止时,有没有办法找出项目的价值是什么?
编辑1:
在我的案例中,可能的解决方案: 经过一番挣扎后,我发现了一件有趣的事情:
在ForEach的Body中添加我的一个自定义活动,我能够获得这样的项目的值:
所以,我的活动来自:CodeActivity
在受保护的覆盖内部String []执行(CodeActivityContext上下文)我正在做这项工作。说实话,这解决了这个问题,但它只能在我的自定义活动中使用。例如,如果我将WriteLine放在那里,我将无法检索该值。
答案 0 :(得分:1)
您可以通过检查ModelItem树父级并检查DelegeateInArgument来访问ForEach活动的DelegeateInArgument。如果您需要一个特定的代码示例来实现这一点,我可能需要一些时间来编写示例代码。由于我做了很长时间,所以在msdn
上看到我的问题因此,基本上是断点所在的位置,您可以访问变量值,因为这些变量值的活动范围为“变量”。但是,'item'变量实际上只能从父循环活动中访问。因此,您必须获取当前执行活动的模型项,然后遍历树以查找包含所需DelegateInArgument的父项。
你能真正完成你想要达到的目标吗?当您在重新托管的设计器中调试工作流时,是否要在用户更改UI时向用户显示变量值?
编辑 - 添加了跟踪示例
因此,当您想要在执行工作流程期间显示变量值时,我们需要使用跟踪来实现此目的。在示例中,您使用作者已经实现了一些基本跟踪。因此,要实现扩展变量跟踪,您需要更改跟踪配置文件。
首先修改WorkflowDesignerHost.xaml.cs文件,改变RunWorkflow方法,以定义SimulatorTrackingParticipant,如下所示。
SimulatorTrackingParticipant simTracker = new SimulatorTrackingParticipant()
{
TrackingProfile = new TrackingProfile()
{
Name = "CustomTrackingProfile",
Queries =
{
new CustomTrackingQuery()
{
Name = all,
ActivityName = all
},
new WorkflowInstanceQuery()
{
**States = {all },**
},
new ActivityStateQuery()
{
// Subscribe for track records from all activities for all states
ActivityName = all,
States = { all },
**Arguments = {all},**
// Extract workflow variables and arguments as a part of the activity tracking record
// VariableName = "*" allows for extraction of all variables in the scope
// of the activity
Variables =
{
{ all }
}
}
}
}
};
现在,这将正确捕获所有工作流实例状态,而不仅仅是“已启动/已完成”。您还将捕获记录跟踪数据的每个活动的所有参数,而不仅仅是变量。这很重要,因为“变量”感兴趣的是(如前所述)DelegateInArgument。
因此,一旦我们更改了跟踪配置文件,我们还需要更改SimulatorTrackingParticipant.cs以提取我们正在跟踪的其他数据。
如果更改OnTrackingRecordReceived方法以包含以下部分,则这些部分将捕获变量数据以及执行期间的Argument数据。
protected void OnTrackingRecordReceived(TrackingRecord record, TimeSpan timeout)
{
System.Diagnostics.Debug.WriteLine(
String.Format("Tracking Record Received: {0} with timeout: {1} seconds.", record, timeout.TotalSeconds)
);
if (TrackingRecordReceived != null)
{
ActivityStateRecord activityStateRecord = record as ActivityStateRecord;
if (activityStateRecord != null)
{
IDictionary<string, object> variables = activityStateRecord.Variables;
StringBuilder vars = new StringBuilder();
if (variables.Count > 0)
{
vars.AppendLine("\n\tVariables:");
foreach (KeyValuePair<string, object> variable in variables)
{
vars.AppendLine(String.Format(
"\t\tName: {0} Value: {1}", variable.Key, variable.Value));
}
}
}
if (activityStateRecord != null)
{
IDictionary<string, object> arguments = activityStateRecord.Arguments;
StringBuilder args = new StringBuilder();
if (arguments.Count > 0)
{
args.AppendLine("\n\tArgument:");
foreach (KeyValuePair<string, object> argument in arguments)
{
args.AppendLine(String.Format(
"\t\tName: {0} Value: {1}", argument.Key, argument.Value));
}
}
//bubble up the args to the UI for the user to see!
}
if((activityStateRecord != null) && (!activityStateRecord.Activity.TypeName.Contains("System.Activities.Expressions")))
{
if (ActivityIdToWorkflowElementMap.ContainsKey(activityStateRecord.Activity.Id))
{
TrackingRecordReceived(this, new TrackingEventArgs(
record,
timeout,
ActivityIdToWorkflowElementMap[activityStateRecord.Activity.Id]
)
);
}
}
else
{
TrackingRecordReceived(this, new TrackingEventArgs(record, timeout,null));
}
}
}
希望这有帮助!