[英]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.