使用WF4.5在运行时在try / catch活动中包装现有工作流

时间:2017-04-23 00:32:21

标签: c# workflow-foundation-4 workflow-foundation

WF4.5的使用现在看起来很吓人,所以对于那里的所有WF4.5专家来说,请花点时间阅读一下,看看你是否可以帮助我。

我尝试在运行时围绕现有工作流活动添加try / catch活动。

你为什么这么问?我需要确保我的工作流程永远不会崩溃,因为我在所有我需要返回的各种活动中使用数据是否发生了未处理的异常,但OnUnhandledException没有返回任何值。

我尝试使用命令式编码和创建实际活动来实现,但我无法弄清楚如何将参数从动态活动中创建的try / catch活动传递给我尝试部分的工作流程。

这是try / catch功能:

    public static Activity TryCatchWrap(Activity runtimeActivity)
    {
        var dataObject = new InOutArgument<DataObject>();

        var ex = new DelegateInArgument<Exception> { Name = "Ex" };

        Activity workflowTryCatch = new DynamicActivity()
        {
            Properties =
            {
                new DynamicActivityProperty
                {
                    Name = "DataObject",
                    Type = typeof(InOutArgument<DataObject>),
                    Value = dataObject
                }
            },
            Implementation = () => new Sequence
            {
                Activities =
                {
                    new WriteLine
                    {
                        Text = new InArgument<string>((ctx) => "Hello1 : " +
                               dataObject.Get(ctx).ApplicationName)
                    },
                    runtimeActivity
                }
            }
        };

        return workflowTryCatch;
    }

如您所见,我在TryCatch中创建了一个DynamicActivity活动,创建了一个属性调用DataObject,并将其Implementation设置为runtimeActivity。

我的runtimeActivity活动,也是一个Dynamic Activity,包含一个流程图活动(以及更多活动),使用以下命令从XAML文件加载:

var activity = ActivityXamlServices.Load(
    fileName,
    new ActivityXamlServicesSettings()
    {
       CompileExpressions = false,
    });

我需要的是将DataObject从TryCatch活动传递到运行时活动,该活动在&#39;尝试&#39; TryCatch

的部分

我怎样才能做到这一点。我尝试了很多组合,这些组合太多了,无法列出各种错误。我读了无数文章,但无济于事,但我显然遗漏了一些东西。

如果我使用workflow designer,我会在几秒钟内启动并运行我所需的方案,认为它稍有不同,因为我将TryCatch添加为第一个元素在我的FlowChart中,然后在TryCatch内,我将Try部分设置为我需要的任何工作流程。

如果有不同的方法可以达到这个目的,我可以接受任何建议。

任何帮助都会非常感激,因为我完全停顿了。

感谢。

UPDATE-1:

我只是另一种方式,我以编程方式从我的flowchart中提取DynamicActivity。一旦我有流程图,然后我提取StartNode并尝试用一个新的替换它,其中包括try / catch,并且Try已被设置为最初与StartNode关联的动作,但这仍然无效。

        var fullWorkflow = WorkflowInspectionServices.GetActivities(workflow);
        var flowchart = (Flowchart)fullWorkflow.First();
        var startNode = (FlowStep)flowchart.StartNode;
        var startNodeAction = startNode.Action;

        flowchart.StartNode = null;

        var ex = new DelegateInArgument<Exception> { Name = "Exception" };

        var tryCatch = new TryCatch();
        var catchException = new Catch<Exception>();
        var catchActivityAction = new ActivityAction<Exception>();

        catchActivityAction.Argument = ex;
        catchActivityAction.Handler = new Assign<Exception>()
        {
            To = new OutArgument<Exception>(new
            VisualBasicReference<Exception>("DataObject.Exception")),
            Value = new InArgument<Exception>(
            new VisualBasicValue<Exception>("Exception"))
        };

        catchException.Action = catchActivityAction;

        tryCatch.Try = startNodeAction;
        tryCatch.Catches.Add(catchException);

        startNode.Action = tryCatch;
        flowchart.StartNode = startNode;

        Activity workflowTryCatch = new DynamicActivity()
        {
            DisplayName = "HelloWorld",
            Properties =
            {
                new DynamicActivityProperty
                {
                    Name = "DataObject",
                    Type = typeof(InOutArgument<DataObject>),
                    //Value = argDataObject
                }
            },
            Implementation = () => flowchart
        };

我在运行时遇到以下错误:

An unhandled exception of type 'System.Activities.InvalidWorkflowException' occurred in 
System.Activities.dll

Additional information: The following errors were encountered while processing the 
workflow tree:

'HelloWorld': The private implementation of activity '1: HelloWorld' has 
the following validation error:   Compiler error(s) encountered processing
expression "DataObject.Exception".

Type 'DataObject' is not defined.

'HelloWorld': The private implementation of activity '1: HelloWorld' has 
the following validation error:   Compiler error(s) encountered processing
expression "DataObject.ApplicationName".

Type 'DataObject' is not defined.

有任何想法/建议吗?

感谢。

1 个答案:

答案 0 :(得分:0)

我最终自己弄清楚了!!如果你问我我会感到痛苦,而且我不能100%确定这是否是正确的方法,但现在我正在正式创建一个DynamicActivity我正在通过我的复杂InOutArgument然后,它会添加一个TryCatch活动,触发我传递给它的Flowchart

如果发生任何未处理的异常,将在我的复杂对象即DataObject中捕获并设置它们。

对我而言,重要的部分是工作流程是否成功运行,它将始终使用在特定Flowchart中捕获的任何信息返回我的复杂对象。

现在已经说过,它运作得很好,但我没有测试过表演,但希望它不会降低太多。

这就是我实现它的方式。我创建了以下函数:

    public static Activity CreateNew(Flowchart flowchart)
    {
        var inProperty = new DynamicActivityProperty
        {
            Name = "DataObject",
            Type = typeof(InOutArgument<DataObject>)
        };

        var ex = new DelegateInArgument<Exception> { Name = "exception" };

        var tryCatch = new TryCatch();
        var tryCatchException = new Catch<Exception>()
        {
            Action = new ActivityAction<Exception>()
            {
                Argument = ex,
                Handler =
                new Sequence
                {
                    Activities =
                    {
                        new Assign<Exception>
                        {
                            To = new VisualBasicReference<Exception>() 
                            {ExpressionText = "DataObject.Exception"},
                            Value = new InArgument<Exception>(ex)
                        },
                        new WriteLine()
                        {
                            Text = new InArgument<string>(new VisualBasicValue<string>() 
                           { ExpressionText = "DataObject.Exception.Message"})
                        }
                    }
                }
            }
        };

        var activity = new DynamicActivity()
        {
            Implementation = () => new Flowchart
            {
                StartNode = new FlowStep
                {
                    Action = tryCatch
                }
            },
            Properties = { inProperty }
        };

        tryCatch.Try = flowchart;
        tryCatch.Catches.Add(tryCatchException);

        AddVbSetting(activity);

        return activity;
    }

上面将运行,但我传递给它的流程图包含一个或多个导入的命名空间。我认为它会按原样运行,但事实并非如此。

我不得不将它们重新添加到新活动中。现在,AddVbSetting只导入/添加我的复杂对象的命名空间,它工作正常,但可能有些情况下你需要添加其他命名空间,所以这个方法需要扩展,但希望,这将是直截了当的。

AddVbSettings的代码是:

    private static void AddVbSetting(Activity activity)
    {
        var settings = new VisualBasicSettings
        {
            ImportReferences =
            {
                new VisualBasicImportReference
                {
                    Assembly = typeof(DataObject).Assembly.GetName().Name,
                    Import = typeof(DataObject).Namespace
                }
            }
        };
        VisualBasic.SetSettings(activity, settings);
    }

我花了很多时间在一些本来应该很简单的东西上,看着它,现在看来显而易见,将所有部分放在一起实际上是一场噩梦!花了很多时间(我觉得这真的很愚蠢!)天来弄清楚并阅读无数文章,上帝知道写了多少原型,更不用说异常后的异常!!

我希望如果那里的任何人仍然使用WF它会对你有所帮助,并为你解除它给我带来的麻烦!很高兴终于结束了......直到明天:)反正!

PS:最终解决方案是流程图中的一个流程图,可能不需要它,我明天可能会修改它。我以为在有人强调这是一个重大缺陷之前我会提到它!