我们知道,WF允许我们以代码方式创建自己的活动,我们可以根据自己的要求来继承不同的活动基类。
基类 | 用途 |
Activity | 由其他活动组成的活动 |
CodeActivity | 可以控制工作流执行的活动 |
AsyncCodeActivity | 可以在工作流执行过程中进行异步操作的活动 |
NativeActivity | 由其他活动组成的活动,并且可以访问工作流运行时 |
1、在我们现有的解决方案中添加一个活动设计器库HelloWorkflow.Activities
2、删除项目中原有的ActivityDesigner1.xaml,添加活动WriteTwoLines.xaml.
3、向设计器中添加一个Sequence活动,为此活动创建两个输入参数(string类型)Line1和Line2,然后在Sequence活动中添加两个WriteLine基元,分别输出Line1和Line2的值。
我们刚刚创建了第一个自定义活动WriteTwoLines,这个活动的创建方式是:组合了WF提供的活动。
4、现在我们开始创建更为复杂的自定义活动,其中一个活动DiagnosticTraceActivity用于跟踪程序运行,另一个活动是PrePostSequenceActivity(顾名思义,是在用户提供的活动运行前后加上Pre(预处理)和Post(尾处理)操作)。而且我们希望我们的新活动在设计器窗口中能够显示成下面的样子
要达到这样的效果,我们必须编写四个类,类DiagnosticTrace.cs和PrePostSequence.cs用于继承Activity类,以实现业务逻辑;另外类DiagnosticTraceDesigner.xaml和PrePostSequenceDesigner.xaml则用wpf的语法编写,用以界面显示;
4.1 创建DiagnosticTrace.cs
该类继承于CodeActivity,同时从图中可以看到该活动有三个成员,Category和Level是设计时可赋值的成员,而Text是在设计时和运行时都可以赋值的成员。所有的成员都以属性的形式存在于活动中。
[System.ComponentModel.DefaultValue(null)]
public InArgument<string> Text { get; set; }
/// <summary> 跟踪类型 </summary>
[System.Windows.Markup.DependsOn("Text")]
[DefaultValue(null)]
public string Category { get; set; }
/// <summary> 当前信息的跟踪级别 </summary>
[DependsOn("Category")]
[DefaultValue("Off")]
public System.Diagnostics.TraceLevel Level { get; set; }
其中DependsOnAttribute指示特性化属性依赖于另一个属性的值,如Category依赖于Text属性的值,该设置在序列化XAML或在WPF中使用Setter时会用到。除了定制一些属性之外,自定义活动最重要的就是重写基类的Execute方法,表示活动的执行过程。该方法只有一个参数CodeActivityContext context 是执行活动时所处的执行上下文。
/// <summary>在派生类中实现时,执行该活动</summary>
protected override void Execute(CodeActivityContext context)
{
//context执行活动时所处的执行上下文。GetValue获取输入参数Text的值
string text = context.GetValue(this.Text);
switch (Level)
{
//输出错误处理消息
case System.Diagnostics.TraceLevel.Error:
System.Diagnostics.Trace.TraceError(text);
break;
//输出信息性消息、警告和错误处理消息
case System.Diagnostics.TraceLevel.Info:
Trace.TraceInformation(text);
break;
//输出所有调试和跟踪消息
case System.Diagnostics.TraceLevel.Verbose:
Trace.WriteLine(text, Category);
break;
case System.Diagnostics.TraceLevel.Warning:
//使用指定的消息向 System.Diagnostics.Trace.Listeners 集合中的跟踪侦听器中写入警告消息
Trace.TraceWarning(text);
break;
}
//not(不输出跟踪和调试消息)
if (Level != System.Diagnostics.TraceLevel.Off)
{
//CustomTrackingRecord包含由运行时跟踪基础结构在引发自定义跟踪记录时发送到跟踪参与者的数据。
CustomTrackingRecord trackRecord = new System.Activities.Tracking.CustomTrackingRecord(Category, Level);
trackRecord.Data.Add("Text", text);
trackRecord.Data.Add("Category", Category);
//将指定的自定义跟踪记录发送到已注册的全部跟踪提供程序
context.Track(trackRecord);
}
}
缓存元数据,将输入/输出参数,变量,验证信息等加入到基类的元数据集合中
protected override void CacheMetadata(CodeActivityMetadata metadata)
{
var textArg = new RuntimeArgument("Text", typeof(string), ArgumentDirection.In, true);
metadata.AddArgument(textArg);
if (string.IsNullOrEmpty(Category))
metadata.