基于使用NamedNetPipes绑定解析端点地址动态创建WCF ServiceHost

时间:2012-06-11 15:22:11

标签: c# wcf

需要一种方法让知名端点上的一个服务返回相对地址的字符串。然后,客户端可以使用这些相对地址连接到端点。 显然,这在某些方面类似于REST,但在这种情况下使用NetNamedPipeBinding为IPC运行Windows服务,因此不需要HTTP。

不希望提前创建端点,因为可能存在大量相对地址,只有客户会感兴趣的一些地址。

所有合同都是事先知道的。

试图找到一个AddressFilterMode的解决方案,但不知道如何配置新的绑定,以便客户端连接到它,UriTemplate但不想使用HTTP框架。没有调查过RoutingService因为受限于.Net 3.5。

客户端的伪代码就像下面那样......

namespace Testing
{
    class RunTest
    {
        static void Test()
        {
            NetNamedPipeBinding namedpipe = new NetNamedPipeBinding();
            ChannelFactory<Contracts.IRoot> factoryRoot =
                new ChannelFactory<Contracts.IRoot>(
                namedpipe
                , new EndpointAddress("net.pipe://localhost/root");
            );
            Contracts.IRoot root = factoryRoot.CreateChannel();
            ICommunicationObject commsRoot = root as ICommunicationObject;
            commsRoot.Open();

            // Service examines address and creates Endpoint dynamically.
            string address = root.SomeFunctionWhichGetsARelativeAddress();

            // IBar service routes endpoint requests internally based on
            // "address" variable.
            ChannelFactory<Contracts.IBar> factoryBar = 
                new ChannelFactory<Contracts.IBar>(
                namedpipe
                , new EndpointAddress("net.pipe://localhost/root/IBar/" +
                                       address)
            );
            Contracts.IBar bar = factoryBar.CreateChannel();
            bar.DoSomething();
        }
    } // Ends class RunTest
} // Ends namespace Testing

2 个答案:

答案 0 :(得分:0)

AddressFilterMode.Prefix可能就足够了。使用的实际端点可以在服务方法中通过检查 OperationContextCurrentIncomingMessageHeadersTo

帮助程序代码可以解析端点并从那里执行任何必要的内部处理。 希望服务器端有一些可扩展性,可以简化代码。

主机的伪代码:

namespace Services
{
    [System.ServiceModel.ServiceBehavior(AddressFilterMode =
         System.ServiceModel.AddressFilterMode.Prefix)]
    class BarService : Contracts.IBar
    {
        #region IBar Members

        public void DoSomething()
        {
            System.Uri endpoint = System.ServiceModel.OperationContext.Current.IncomingMessageHeaders.To;
            Console.WriteLine("DoSomething endpoint: {0}", endpoint);
        }
    } // Ends class BarService
} // Ends namespace Services
class RunHost
{
    static void HostIBar()
    {
        System.Uri uriBase = new System.Uri("net.pipe://localhost");
        System.ServiceModel.ServiceHost hostBar =
            new System.ServiceModel.ServiceHost(
            typeof(Services.BarService),
            uriBase);
        hostBar.AddServiceEndpoint(
              typeof(Contracts.IBar) // Type implementedContract
            , namedpipeBinding // System.ServiceModel.Channels.Binding binding
            , "root/IBar" //string address
        );
        hostBar.Open();

        Console.WriteLine("Press <ENTER> to stop...");
        Console.ReadLine();
    }
}

更正:我原先说过这不会将"net.pipe://localhost/root/IBar/1""net.pipe://localhost/root/IBar/2"视为不同的端点,但确实如此。每个都会导致创建并调用自己的WCF服务实例。

另一项更改是在URL样式查询参数中对数据进行编码,而不是将其嵌入到路径中。例如:"net.pipe://localhost/root/IBar?something=1&somethingelse=11""net.pipe://localhost/root/IBar?something=2&somethingelse=22"使用HttpUtility.ParseQueryString

答案 1 :(得分:0)

消息过滤器是可行的方法。您可以使用“前缀”或创建自定义。

WCF Addressing In Depth

从文章的邮件过滤器部分:

  

...它使用消息过滤器来确定匹配的端点(如果有的话)   存在。您可以选择要使用的消息过滤器,也可以选择提供   你自己。这种灵活性使您可以摆脱困境   使用Windows Communication时的传统调度模型   实现除传统SOAP之外的其他东西的基础   例如,这里描述的技术使您能够实现   Windows Communication Foundation上的REST / POX样式服务   消息基础。

顺便说一下,好的问题。我学到了一些东西试图解决这个问题。