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

WF4:宿主No-Service Workflow

Posted on 2010-01-10 14:30  生鱼片  阅读(1988)  评论(4编辑  收藏  举报

我们在使用工作流服务时,一般会在工作流设计中使用Receive等消息活动,然后使用WorkflowServiceHost进行宿主,如果没有Receive活动,工作流就无法接受发送来的消息,这个时候我们可以使用WorkflowHostingEndpoint类:

image

要宿主一个没有服务的工作流,需要继承WorkflowHostingEndpoint并重写OnGetInstanceId,OnGetCreationContext,OnResolveBookmark。首先我们要声明一个服务契约,该契约包含一个创建新实例的服务操作,这个操作要传一个IDictionary<string,object>参数,这个契约隐式被WorkflowHostingEndpoint实现。当宿主这个工作流时,使用WorkflowServiceHost的AddServiceEndpoint方法添加。下面举例说明:

1.下面是项目结构:

clip_image002

2.首先定义服务契约,如下:

[ServiceContract(Name = "IWorkflowCreation")]
public interface IWorkflowCreation

{

        [OperationContract(Name = "Create")]
        Guid Create(IDictionary<string, object> inputs); 

        [OperationContract(Name = "CreateWithInstanceId", IsOneWay = true)]
        void CreateWithInstanceId(Guid instanceId, IDictionary<string, object> inputs); 

        [OperationContract(Name = "ResumeBookmark", IsOneWay = true)]
        void ResumeBookmark(Guid instanceId, string bookmarkName, string message); 

}

3.下面是ResumeBookmarkEndpoint的实现:

namespace CaryCommon

{

    public class ResumeBookmarkEndpoint : WorkflowHostingEndpoint

    { 

        public ResumeBookmarkEndpoint(Binding binding, EndpointAddress address)

            : base(typeof(IWorkflowCreation), binding, address)

        {

        } 

        protected override Guid OnGetInstanceId(object[] inputs, OperationContext operationContext)

        {

            if (operationContext.IncomingMessageHeaders.Action.EndsWith("Create"))

            {

                return Guid.Empty;

            }

            else if (operationContext.IncomingMessageHeaders.Action.EndsWith("CreateWithInstanceId") ||

                    operationContext.IncomingMessageHeaders.Action.EndsWith("ResumeBookmark"))

            {

                return (Guid)inputs[0];

            }

            else

            {

                throw new InvalidOperationException("Invalid Action: " + operationContext.IncomingMessageHeaders.Action);

            }

        } 

        protected override WorkflowCreationContext OnGetCreationContext(object[] inputs, OperationContext operationContext, Guid instanceId, WorkflowHostingResponseContext responseContext)

        {

            WorkflowCreationContext creationContext = new WorkflowCreationContext();
            if (operationContext.IncomingMessageHeaders.Action.EndsWith("Create"))

            {

                Dictionary<string, object> arguments = (Dictionary<string, object>)inputs[0];

                if (arguments != null && arguments.Count > 0)

                {

                    foreach (KeyValuePair<string, object> pair in arguments)

                    {

                        creationContext.WorkflowArguments.Add(pair.Key, pair.Value);

                    }

                }

                responseContext.SendResponse(instanceId, null);

            }

            else if (operationContext.IncomingMessageHeaders.Action.EndsWith("CreateWithInstanceId"))

            {

                Dictionary<string, object> arguments = (Dictionary<string, object>)inputs[0];

                if (arguments != null && arguments.Count > 0)

                {

                    foreach (KeyValuePair<string, object> pair in arguments)

                    {

                        creationContext.WorkflowArguments.Add(pair.Key, pair.Value);

                    }

                }

            }

            else

            {

                throw new InvalidOperationException("Invalid Action: " + operationContext.IncomingMessageHeaders.Action);

            }

            return creationContext;

        }

        protected override System.Activities.Bookmark OnResolveBookmark(object[] inputs, OperationContext operationContext, WorkflowHostingResponseContext responseContext, out object value)

        {

            Bookmark bookmark = null;

            value = null;

            if (operationContext.IncomingMessageHeaders.Action.EndsWith("ResumeBookmark"))

            {

                bookmark = new Bookmark((string)inputs[1]);

                value = (string)inputs[2];

            }

            else

            {

                throw new NotImplementedException(operationContext.IncomingMessageHeaders.Action);

            }

            return bookmark;

        }

    } 

   }

 

4.下面完成工作流,首先定义一个自定义活动如下:

namespace CaryHost

{

    public sealed class CaryActivity<T> : NativeActivity<T>

    {

        public string BookmarkName { get; set; } 

        protected override bool CanInduceIdle

        {

            get { return true; }

        } 

        protected override void Execute(NativeActivityContext context)

        {

            context.CreateBookmark(BookmarkName, new BookmarkCallback(OnBookmarkCallback));

        } 

        void OnBookmarkCallback(NativeActivityContext context, Bookmark bookmark, object state)

        {

            this.Result.Set(context, (T)state);

        }       

    }

} 

5.工作流设计如下:

clip_image004 

6.服务端宿主程序如下:

namespace CaryHost

{

    class Program

    {

        static void Main(string[] args)

        {         

            WorkflowServiceHost host = null;

            try

            {             

                host = new WorkflowServiceHost(new Workflow1(), new Uri("http://localhost"));

                ResumeBookmarkEndpoint endpoint = new ResumeBookmarkEndpoint(new BasicHttpBinding(),
                    new EndpointAddress(new Uri("http://localhost/CaryService1.xaml")));            

                host.AddServiceEndpoint(endpoint);

                host.Open();

                Console.WriteLine("Host Started:"+endpoint.Address);

                Console.ReadLine();

            }

            catch (Exception ex)

            {

                Console.WriteLine(ex);

            }

            finally

            {

                if (host != null)

                {

                    host.Close();

                }

            }

        } 

    }

} 

7.客户端调用如下:

namespace CaryClient

{

    class Program

    {

        static void Main(string[] args)

        {

            ResumeBookmarkEndpoint endpoint = new ResumeBookmarkEndpoint(new BasicHttpBinding(),
                 new EndpointAddress(new Uri("http://localhost/CaryService1.xaml"))); 

            IWorkflowCreation client = new ChannelFactory<IWorkflowCreation>(endpoint.Binding, endpoint.Address).CreateChannel(); 

            Guid id = client.Create(null);

            Console.WriteLine("WorkflowApplication {0} Created", id);

            client.ResumeBookmark(id, "cary", "Hello Wold!");

        }

    }

}

8.结果如下:

clip_image006