和.NET Framework中提供Action<T>和Func<>系列类似,只不过这个是构建在WF引擎之上的,利用该特性可以在我们开发的通用的流程中,可以让用户加入自己的业务逻辑。
下面是一个简单的例子
1. 首先开发一个自定义活动如下:
public class CaryActivity : NativeActivity
{
public ActivityAction<string> customAction { get; set; }
protected override void CacheMetadata(NativeActivityMetadata metadata)
{
metadata.AddDelegate(customAction);
}
protected override void Execute(NativeActivityContext context)
{
context.ScheduleAction<string>(customAction, "custom action",new CompletionCallback(this.onCompleted),null);
}
public void onCompleted(NativeActivityContext context, ActivityInstance completedInstance)
{
Console.WriteLine("onCompleted");
}
}
2. 我们在活动中定义了一个ActivityAction,用户在使用该活动的时候就可以加入自己的逻辑。如下
class Program
{
static void Main(string[] args)
{
DelegateInArgument<string> argument = new DelegateInArgument<string>("itemtest");
CaryActivity caryac = new CaryActivity()
{
customAction = new ActivityAction<string>()
{
Argument = argument,
Handler = new WriteLine() { Text = new InArgument<string>((context) => "This is " + argument.Get(context)) }
}
};
WorkflowInvoker.Invoke(caryac);
Console.ReadLine();
}
}
3. WF4自己提供很多开箱即用的活动,都使用该特性,比如我们可以利用Reflector来看下ForEach的代码如下:
[ContentProperty("Body")] public sealed class ForEach : NativeActivity { // Fields [CompilerGenerated] private ActivityAction<object> <Body>k__BackingField; [CompilerGenerated] private InArgument<IEnumerable> <Values>k__BackingField; private CompletionCallback onChildComplete; private Variable<IEnumerator> valueEnumerator = new Varriable<IEnumerator>();
// Methods protected override void CacheMetadata(NativeActivityMetadata metadata) { RuntimeArgument argument = new RuntimeArgument("Values", typeof(IEnumrerable), ArgumentDirection.In, true); metadata.Bind(this.Values, argument); metadata.AddArgument(argument); metadata.AddDelegate(this.Body); metadata.AddImplementationVariable(this.valueEnumerator); }
protected override void Execute(NativeActivityContext context) { IEnumerable enumerable = this.Values.Get(context); if (enumerable == null) { throw FxTrace.Exception.AsError(new InvalidOperationException(SR.ForEachRequiresNonNullValues(base.DisplayName))); } IEnumerator enumerator = enumerable.GetEnumerator(); this.valueEnumerator.Set(context, enumerator); if ((this.Body == null) || (this.Body.Handler == null)) { while (enumerator.MoveNext()) { } this.OnForEachComplete(enumerator); } else { this.InternalExecute(context, enumerator); } }
private void GetStateAndExecute(NativeActivityContext context, ActivityInstance completedInstance) { IEnumerator valueEnumerator = this.valueEnumerator.Get(context); this.InternalExecute(context, valueEnumerator); }
private void InternalExecute(NativeActivityContext context, IEnumerator valueEnumerator) { if (!valueEnumerator.MoveNext()) { this.OnForEachComplete(valueEnumerator); } else if (context.ExecutingActivityInstance.IsCancellationRequested) { context.MarkCanceled(); this.OnForEachComplete(valueEnumerator); } else { context.ScheduleAction<object>(this.Body, valueEnumerator.Current, this.OnChildComplete, null); } }
private void OnForEachComplete(IEnumerator valueEnumerator) { IDisposable disposable = valueEnumerator as IDisposable; if (disposable != null) { disposable.Dispose(); } }
// Properties [DefaultValue((string) null), DependsOn("Values")] public ActivityAction<object> Body { [CompilerGenerated, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] get { return this.<Body>k__BackingField; } [CompilerGenerated, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] set { this.<Body>k__BackingField = value; } }
private CompletionCallback OnChildComplete { get { if (this.onChildComplete == null) { this.onChildComplete = new CompletionCallback(this.GetStateAndExecute); } return this.onChildComplete; } }
[RequiredArgument, DefaultValue((string) null)] public InArgument<IEnumerable> Values { [CompilerGenerated, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] get { return this.<Values>k__BackingField; } [CompilerGenerated, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] set { this.<Values>k__BackingField = value; } } } |
以看到他的Body就是一个ActivityAction,去执行用户自己指定的Body部分活动,并循环去枚举直到其中的逻辑执行完成为止。
本文转自生鱼片博客园博客,原文链接:http://www.cnblogs.com/carysun/archive/2010/02/04/WF4-ActivityAction.html,如需转载请自行联系原作者