限制客户对工作流程的了解

时间:2010-11-22 20:23:28

标签: wcf workflow-foundation workflow-foundation-4

情景:

  • .NET 4下的Windows Workflow Foundation(WF)
  • 部署为WCF服务的工作流程
  • 多个接收操作,所有操作都具有相同的参数
  • 操作名称与活动名称匹配
  • 使用SQL Server工作流持久性
  • (无SharePoint)

默认情况下,当您添加服务引用并生成代理时,工作流的知识将嵌入到客户端中。客户端知道可用的WCF方法。

我希望将工作流与客户端分离,实际上创建了一个“通用”客户端,可以使用符合某些约定的任何工作流。客户端将查询SQL实例存储以确定给定实例正在等待的活动/操作/书签(这已经是标准列 - ActiveBookmarks),然后将该选择呈现给用户。

这样可以更改工作流,而无需重新编译/重新部署客户端。一些商业BPM系统以这种方式工作;您可以添加新的人工客户端活动,它们会自动显示在客户端的工作队列中。一切都是动态可发现的。

如何做到这一点?是否需要使用Reflection.Emit动态生成代理?如果每个操作使用不同的服务合同会更容易吗?

1 个答案:

答案 0 :(得分:1)

我在几个项目中完成了这项工作,它运作得很好。并且不需要使用Reflection.Emit,因为WCF具有所有必需的基础设施。

例如,以下代码将调用默认工作流服务模板,您需要做的就是提供正确的URL。

class Program
{
    static void Main(string[] args)
    {

        var factory = new ChannelFactory<IMyService>(new BasicHttpBinding(), new EndpointAddress("http://localhost:9199/Service1.xamlx"));
        var proxy = factory.CreateChannel();
        var response = proxy.GetData(new GetDataRequest() { Value = 42 });
        Console.WriteLine(response.Value);
        Console.ReadLine();
    }
}

[ServiceContract(Name = "IService")]
interface IMyService
{
    [OperationContract]
    GetDataResponse GetData(GetDataRequest request);
}

[MessageContract(IsWrapped = false)]
class GetDataRequest
{
    [MessageBodyMember(Name = "int", 
        Namespace = "http://schemas.microsoft.com/2003/10/Serialization/")]
    public int Value { get; set; }
}

[MessageContract(IsWrapped = false)]
class GetDataResponse
{
    [MessageBodyMember(Name = "string", 
        Namespace = "http://schemas.microsoft.com/2003/10/Serialization/")]
    public string Value { get; set; }
}

如果您需要更大的灵活性,您还可以创建一个ServiceIntered类型为Message in和out,以及一个带有Name =“*”的OperationContract,您可以根据需要手动创建WCF消息。