繁体   English   中英

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

[英]Wrap an existing workflow in a try/catch activity at run-time with WF4.5

如今,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;
    }

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

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

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

我需要的是从通过数据对象TryCatch活动,这是在的“尝试”一节中提供运行时的活动TryCatch

我该如何实现。 我尝试了很多组合,这些组合太多了,更不用说各种错误了。 我读了无数的文章,但无济于事,但我显然缺少了一些东西。

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

如果有其他方法可以实现这一目标,我欢迎您提出任何建议。

由于我完全停滞不前,任何帮助将不胜感激。

谢谢。

更新1:

我以另一种方式进行另一种尝试,即以编程方式从DynamicActivity提取flowchart 有了流程图后,我将提取StartNode并尝试用新的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.

有什么想法/建议吗?

谢谢。

我最终自己解决了!! 如果您问我,我会痛不欲生,但我不是100%地确定这是否是正确的解决方法,但是现在我正式创建了一个DynamicActivity ,我将复杂的InOutArgument传递给了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:最终解决方案是流程图中可能不需要的流程图,我明天可能会对其进行修改。 我只是想在有人强调这是一个重大缺陷之前就提到了它!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM