【问题标题】:HOW to get Context of WorkflowApplication?如何获取 WorkflowApplication 的上下文?
【发布时间】:2012-07-09 14:28:08
【问题描述】:

我正在制作一个类似于 Visual Workflow Tracking* 的工作流设计器。

我想添加一个新控件来调试 wf,但我不知道如何访问 wf 上下文

要运行 WF 我使用这个:

 WFApplication wfApp = new WorkflowApplication(act, inputs);

我的想法是当我接收跟踪事件时,获取 wfApp 的上下文,获取变量或参数值。

有可能吗?

*您可以从以下位置下载 VisualStudioTracking 代码: Windows Communication Foundation (WCF) and Windows Workflow Foundation (WF) Samples for .NET Framework 4 进而 :\WF_WCF_Samples\WF\Application\VisualWorkflowTracking*

【问题讨论】:

    标签: workflow-foundation-4


    【解决方案1】:

    我终于解决了这个问题。

    首先,我从 xaml 获取所有参数名称和工作流变量。

        class XamlHelper
        {   
    
        private string xaml;
    
        public XamlHelper(string xaml)
        {           
            this.xaml = xaml;
    
            DynamicActivity act = GetRuntimeExecutionRoot(this.xaml);
            ArgumentNames = GetArgumentsNames(act);
    
         GetVariables(act);
        }
    
        private void GetVariables(DynamicActivity act)
        {
            Variables = new List<string>();
            InspectActivity(act);
    
    
        }
    
        private void InspectActivity(Activity root)
        {
    
    
            IEnumerator<Activity> activities =
                WorkflowInspectionServices.GetActivities(root).GetEnumerator();
    
    
            while (activities.MoveNext())
            {
    
                PropertyInfo propVars = activities.Current.GetType().GetProperties().FirstOrDefault(p => p.Name == "Variables" && p.PropertyType == typeof(Collection<Variable>));
                if (propVars != null)
                {
                    try
                    {
                        Collection<Variable> variables = (Collection<Variable>)propVars.GetValue(activities.Current, null);
                        variables.ToList().ForEach(v =>
                        {
                            Variables.Add(v.Name);
    
                        });
                    }
                    catch
                    {
    
                    }
                }
                InspectActivity(activities.Current);
            }
        }
    
    
    
    
    
        public List<string> Variables
        {
            get;
            private set;
        }
    
        public List<string> ArgumentNames
        {
            get;
            private set;
        }
    
    
        private DynamicActivity GetRuntimeExecutionRoot(string xaml)
        {
    
    
            Activity root = ActivityXamlServices.Load(new StringReader(xaml));
    
    
                WorkflowInspectionServices.CacheMetadata(root);
    
            return root as DynamicActivity;
    
        }
    
        private List<string> GetArgumentsNames(DynamicActivity act)
        {
            List<string> names = new List<string>();
            if (act != null)
            {
                act.Properties.Where(p => typeof(Argument).IsAssignableFrom(p.Type)).ToList().ForEach(dp =>
                {
                    names.Add(dp.Name);
                });
    
            }
    
            return names;
        }
    
    }
    

    其次,我使用这些参数和变量名创建跟踪

        private static WFTrace CreateTrace(List<string> argumentNames, List<string> variablesNames)
        {
            WFTrace trace = new WFTrace();
            trace.TrackingProfile = new TrackingProfile()
            {
                ImplementationVisibility = ImplementationVisibility.All,
                Name = "CustomTrackingProfile",
                Queries = 
                    {
                        new CustomTrackingQuery() 
                        {
                         Name = all,
                         ActivityName = all
                        },
                        new WorkflowInstanceQuery()
                        {
    
    
                             // Limit workflow instance tracking records for started and completed workflow states
                            States = {WorkflowInstanceStates.Started, WorkflowInstanceStates.Completed },
                       }
                    }
            };
    
            trace.TrackingProfile.Queries.Add(GetActivityQueryState(argumentNames, variablesNames));
    
            return trace;
        }
    

    然后调用wf并添加traceextension。

    亚当这是代码

      private TrackingQuery GetActivityQueryState(List<string> argumentNames, List<string> variablesNames)
            {
                ActivityStateQuery query = new ActivityStateQuery()
                {
                    ActivityName = "*",
                    States = { ActivityStates.Executing, ActivityStates.Closed }
                };
                if (argumentNames != null)
                {
                    argumentNames.Distinct().ToList().ForEach(arg =>
                    {
                        query.Arguments.Add(arg);
                    });
                }
                if (variablesNames != null)
                {
                    variablesNames.Distinct().ToList().ForEach(v =>
                    {
                        query.Variables.Add(v);
                    });
                }
                return query;
            }
    

    【讨论】:

    • 嗨,你能发布你对GetActivityQueryState的实现吗?
    • 我正在尝试做同样的事情 - 每次我的工作流程恢复时,我都需要收集在根声明的变量的值 - 但是我没有收到任何 Track 回调触发的信息需要。
    【解决方案2】:

    您可以在工作流运行时使用Tracking Participants 提取variables and arguments

    【讨论】:

    • 好的,谢谢。但跟踪参与者仅捕获当前活动的变量。所以如果我需要检查 wf 全局变量的值...我需要保存所有变量 wf ,在活动开始时推送 vars 并在活动完成时弹出。
    • 跟踪参与者可以捕获范围内每个变量的值,而不仅仅是在触发事件的活动中定义的变量。不要使用“*”通配符,因为它只跟踪当前活动变量,而是使用命名变量。
    • 但是我不知道 vars 的名称,我有一个 WorkflowDesigner 控件,并且用户创建了 vars、flowchars、sequncie 等...
    • 鉴于带有 '*' 的跟踪变量将使用应该告诉您的当前活动导出所有变量。
    【解决方案3】:

    我尝试用这个跟踪参与者跟踪变量

        private static VisualTrackingParticipant VisualTracking()
        {
            String all = "*";
            VisualTrackingParticipant simTracker = new VisualTrackingParticipant()
            {
                TrackingProfile = new TrackingProfile()
                {
                    Name = "CustomTrackingProfile",
                    Queries = 
                        {
                            new CustomTrackingQuery() 
                            {
                                Name = all,
                                ActivityName = all
                            },
                            new WorkflowInstanceQuery()
                            {
                                // Limit workflow instance tracking records for started and completed workflow states
                               // States = { WorkflowInstanceStates.Started, WorkflowInstanceStates.Completed },
                               States={all}
                            },
                            new ActivityStateQuery()
                            {
                                // Subscribe for track records from all activities for all states
                                ActivityName = all,
                                States = { 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 }   
                                },
                                Arguments={ {all}}
                            }   
                        }
                }
            };
            return simTracker;
        }
    

    这是 VisualTrackingParticipant

    public class VisualTrackingParticipant : System.Activities.Tracking.TrackingParticipant
    {
        public event EventHandler<TrackingEventArgs> TrackingRecordReceived;
        public Dictionary<string, Activity> ActivityIdToWorkflowElementMap { get; set; }
    
    
        protected override void Track(TrackingRecord record, TimeSpan timeout)
        {
            OnTrackingRecordReceived(record, timeout);
        }
    
        //On Tracing Record Received call the TrackingRecordReceived with the record received information from the TrackingParticipant. 
        //We also do not worry about Expressions' tracking data
        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)
                // && (!activityStateRecord.Activity.TypeName.Contains("System.Activities.Expressions")))
                {
                    Activity act = null;
                    ActivityIdToWorkflowElementMap.TryGetValue(activityStateRecord.Activity.Id, out act);
    
    
                    TrackingRecordReceived(this, new TrackingEventArgs(
                                                    record,
                                                    timeout,
                                                    act
                                                    )
    
                        );
    
    
                }
                else
                {
                    TrackingRecordReceived(this, new TrackingEventArgs(record, timeout, null));
                }
    
            }
        }
    }
    
    //Custom Tracking EventArgs
    public class TrackingEventArgs : EventArgs
    {
        public TrackingRecord Record {get; set;}
        public TimeSpan Timeout {get; set;}
        public Activity Activity { get; set; }
    
        public TrackingEventArgs(TrackingRecord trackingRecord, TimeSpan timeout, Activity activity)
        {
            this.Record = trackingRecord;
            this.Timeout = timeout;
            this.Activity = activity;
        }
    }
    

    如果我跟踪这个 wf:

    <Activity mc:Ignorable="sap" x:Class="Microsoft.Samples.Workflow" xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities" xmlns:av="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mv="clr-namespace:Microsoft.VisualBasic;assembly=System" xmlns:mva="clr-namespace:Microsoft.VisualBasic.Activities;assembly=System.Activities" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:s1="clr-namespace:System;assembly=System" xmlns:s2="clr-namespace:System;assembly=System.Xml" xmlns:s3="clr-namespace:System;assembly=System.Core" xmlns:sa="clr-namespace:System.Activities;assembly=System.Activities" xmlns:sad="clr-namespace:System.Activities.Debugger;assembly=System.Activities" xmlns:sap="http://schemas.microsoft.com/netfx/2009/xaml/activities/presentation" xmlns:scg="clr-namespace:System.Collections.Generic;assembly=System" xmlns:scg1="clr-namespace:System.Collections.Generic;assembly=System.ServiceModel" xmlns:scg2="clr-namespace:System.Collections.Generic;assembly=System.Core" xmlns:scg3="clr-namespace:System.Collections.Generic;assembly=mscorlib" xmlns:sd="clr-namespace:System.Data;assembly=System.Data" xmlns:sd1="clr-namespace:System.Data;assembly=System.Data.DataSetExtensions" xmlns:sl="clr-namespace:System.Linq;assembly=System.Core" xmlns:st="clr-namespace:System.Text;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
      <x:Members>
        <x:Property Name="decisionVar" Type="InArgument(x:Boolean)" />
      </x:Members>
      <sap:VirtualizedContainerService.HintSize>666,676</sap:VirtualizedContainerService.HintSize>
      <mva:VisualBasic.Settings>Assembly references and imported namespaces serialized as XML namespaces</mva:VisualBasic.Settings>
      <Flowchart sad:XamlDebuggerXmlReader.FileName="C:\WF_WCF_Samples\WF\Application\VisualWorkflowTracking\CS\VisualWorkflowTracking\Workflow.xaml" sap:VirtualizedContainerService.HintSize="626,636" mva:VisualBasic.Settings="Assembly references and imported namespaces serialized as XML namespaces">
        <Flowchart.Variables>
          <Variable x:TypeArguments="x:String" Name="myStr" />
        </Flowchart.Variables>
        <sap:WorkflowViewStateService.ViewState>
          <scg3:Dictionary x:TypeArguments="x:String, x:Object">
            <x:Boolean x:Key="IsExpanded">False</x:Boolean>
            <av:Point x:Key="ShapeLocation">270,7.5</av:Point>
            <av:Size x:Key="ShapeSize">60,75</av:Size>
            <av:PointCollection x:Key="ConnectorLocation">300,82.5 300,111.5</av:PointCollection>
            <x:Double x:Key="Width">611.5</x:Double>
          </scg3:Dictionary>
        </sap:WorkflowViewStateService.ViewState>
        <Flowchart.StartNode>
          <FlowStep x:Name="__ReferenceID0">
            <sap:WorkflowViewStateService.ViewState>
              <scg3:Dictionary x:TypeArguments="x:String, x:Object">
                <av:Point x:Key="ShapeLocation">179,111.5</av:Point>
                <av:Size x:Key="ShapeSize">242,58</av:Size>
                <av:PointCollection x:Key="ConnectorLocation">300,169.5 300,199.5 280,199.5 280,269.5</av:PointCollection>
              </scg3:Dictionary>
            </sap:WorkflowViewStateService.ViewState>
            <Assign sap:VirtualizedContainerService.HintSize="242,58">
              <Assign.To>
                <OutArgument x:TypeArguments="x:String">[myStr]</OutArgument>
              </Assign.To>
              <Assign.Value>
                <InArgument x:TypeArguments="x:String">PDC Rocks</InArgument>
              </Assign.Value>
            </Assign>
            <FlowStep.Next>
              <FlowStep x:Name="__ReferenceID1">
                <sap:WorkflowViewStateService.ViewState>
                  <scg3:Dictionary x:TypeArguments="x:String, x:Object">
                    <av:Point x:Key="ShapeLocation">174.5,269.5</av:Point>
                    <av:Size x:Key="ShapeSize">211,61</av:Size>
                    <av:PointCollection x:Key="ConnectorLocation">155.33,351.361666666667 155.33,481 204.5,481</av:PointCollection>
                  </scg3:Dictionary>
                </sap:WorkflowViewStateService.ViewState>
                <WriteLine sap:VirtualizedContainerService.HintSize="211,61" Text="[myStr]" />
              </FlowStep>
            </FlowStep.Next>
          </FlowStep>
        </Flowchart.StartNode>
        <x:Reference>__ReferenceID0</x:Reference>
        <x:Reference>__ReferenceID1</x:Reference>
      </Flowchart>
    </Activity>
    

    当活动关闭时,你会收到这个跟踪这个参数

    [Arg] 值 = PDC 岩石 [Arg] To = PDC 岩石

    我不知道值被关联的 var 的名称

    【讨论】:

      猜你喜欢
      • 2023-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-31
      • 1970-01-01
      相关资源
      最近更新 更多