我們在使用工作流服務時,一般會在工作流設計中使用Receive等消息活動,然後使用WorkflowServiceHost進行宿主,如果沒有 Receive活動,工作流就無法接受發送來的消息,這個時候我們可以使用WorkflowHostingEndpoint類:
要宿主一個沒有服務的工作流,需要繼承WorkflowHostingEndpoint並重寫 OnGetInstanceId,OnGetCreationContext,OnResolveBookmark。首先我們要聲明一個服務契約,該契約包含一個創建新實例的服務操作,這個操作要傳一個IDictionary<string,object>參數,這個契約隱式被 WorkflowHostingEndpoint實現。當宿主這個工作流時,使用WorkflowServiceHost的 AddServiceEndpoint方法添加。下面舉例說明:
1.下面是項目結構:
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.工作流設計如下:
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.結果如下:
出處:http://carysun.cnblogs.com/