博客园  :: 首页  :: 联系 :: 订阅 订阅  :: 管理

WF4:AcitivityAction和ActivityFunc

Posted on 2010-02-04 20:29  生鱼片  阅读(1972)  评论(3编辑  收藏  举报

.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://blogs.msdn.com/mwinkle/archive/2009/12/24/swiss-cheese-and-wf4-or-an-introduction-to-activityaction.aspx
http://blogs.msdn.com/mwinkle/archive/2010/01/15/making-swiss-cheese-look-good-or-designers-for-activityaction-in-wf4.aspx

 
http://msdn.microsoft.com
 http://social.msdn.microsoft.com/Forums/en-US/wfprerelease/threads