【问题标题】:WF 4 Rehosted Designer - get foreach InArgument ValueWF 4 Rehosted Designer - 获取 foreach InArgument 值
【发布时间】:2015-04-30 06:48:41
【问题描述】:

看完这篇文章:

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} 我需要一种方法来检查“项目”如何取值 1、2 和 3。

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

编辑 1:

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

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

所以,我的活动来自:CodeActivity

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

【问题讨论】:

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


    【解决方案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 方法以包含以下部分,这些部分将在执行期间捕获变量数据以及参数数据。

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

    希望这会有所帮助!

    【讨论】:

    • ModelService ms = wd.Context.Services.GetService(); IEnumerable 活动 = ms.Find(ms.Root, typeof(DelegateInArgument));我成功地运行了这个,确实,我得到了那个论点,但我不知道在那之后如何检索这个值。
    • 如果您可以访问一段旧代码并在此处发布一些行,那就太好了。我不知道如何进一步解决这个问题。
    • 好的,你能告诉我你在哪里调用 ModelService ms = wd.Context.Services.GetService(); IEnumerable 活动 = ms.Find(ms.Root, typeof(DelegateInArgument)) 来自?所以我可以在正确的上下文中给你一个例子吗?您是使用跟踪来显示调试信息,还是只想显示带有值的消息框?
    • 我将这种方法用于断点机制。 blogs.msdn.com/b/kushals/archive/2009/12/29/…
    • 我一接触到我的电脑就会试一试。非常感谢您的帮助!
    猜你喜欢
    • 2011-08-02
    • 2016-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-25
    • 1970-01-01
    相关资源
    最近更新 更多