WF 4 Rehosted Designer - 获得Foreach InArgument Value

时间:2015-04-30 06:48:41

标签: workflow-foundation-4 workflow-foundation workflow-activity

阅读本文后:

http://blogs.msdn.com/b/tilovell/archive/2009/12/29/the-trouble-with-system-activities-foreach-and-parallelforeach.aspx

我已经按如下方式定义了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。

enter image description here

为了更准确,我已添加了这张照片,并在foreach内的WriteLine活动中添加了一个断点。当执行将在那里停止时,有没有办法找出项目的价值是什么?

编辑1:

在我的案例中,

可能的解决方案: 经过一番挣扎后,我发现了一件有趣的事情:

在ForEach的Body中添加我的一个自定义活动,我能够获得这样的项目的值:

enter image description here

所以,我的活动来自:CodeActivity

受保护的覆盖内部String []执行(CodeActivityContext上下文)我正在做这项工作。说实话,这解决了这个问题,但它只能在我的自定义活动中使用。例如,如果我将WriteLine放在那里,我将无法检索该值。

1 个答案:

答案 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));
            }

        }

    }

希望这有帮助!