WF 4 Rehosted Designer - 获取 foreach InArgument 值

WF 4 Rehosted Designer - get foreach InArgument Value

阅读本文后:

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")
            }
        };
    }
}

一切正常,但是否可以检查在我的案例中名为 "item" 的 DelegeateInArgument 如何更改其值? 所以如果我在变量部分定义了一个数组并用 {1, 2, 3} 我需要一种方法来检查 "item" 如何取值 1、2 然后是 3。

为了更准确,我添加了这张图片,在 foreach 内的 WriteLine activity 上有一个断点。当执行停止时,有没有办法找出 item 的值是什么?

编辑 1:

可能的解决方案 在我的例子中: 经过一番努力,我发现了一件有趣的事情:

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

所以,我的 activity 来自:CodeActivity

protected override String[] Execute(CodeActivityContext context) 我正在做这个 job.To 老实说,这以某种方式解决了这个问题,但它只是可行的在我的自定义活动中。例如,如果我将 WriteLine 放在那里,我将无法检索该值。

您可以通过检查 ModelItem 树的父树并检查 DelegeateInArgument 来访问 ForEach activity 的 DelegeateInArgument。如果您需要一个特定的代码示例来实现这一点,我可能需要一些时间来编写示例代码。因为我已经很久没有这样做了,请参阅我在 msdn

上提出的问题

所以基本上你的断点在哪里,你可以访问变量值,因为这些值是用你的 activity 范围定义的 'variables'。然而 'item' 变量实际上只能从父循环 activity 访问。所以你必须得到当前正在执行的模型项 activity 然后向上遍历树找到包含所需 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 }   
                            }
                        }   
                    }
                }
            };

现在这将正确捕获所有工作流实例状态,而不仅仅是 Started/Completed。您还将捕获每个 activity 上记录跟踪数据而不仅仅是变量的所有参数。这很重要,因为 'variable' 感兴趣的实际上是(如前所述)DelegateInArgument。

因此,一旦我们更改了跟踪配置文件,我们还需要更改 SimulatorTrackingParticipant.cs 以提取我们现在正在跟踪的其他数据。

如果您更改 OnTrackingRecordReceived 方法以包含以下部分,这些部分将在执行期间捕获变量数据和参数数据。

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

        }

    }

希望对您有所帮助!