2

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

不想提前创建端点,因为可能会有大量的相对地址,只有其中一些是客户感兴趣的。

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

尝试使用AddressFilterMode找到解决方案,但不确定如何设置新的 Binding 以便客户端连接到UriTemplate但不想使用 HTTP 框架。由于受限于 .Net 3.5,因此尚未研究RoutingService 。

客户端的伪代码如下所示...

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
4

2 回答 2

0

AddressFilterMode.Prefix可能就足够了。可以通过 OperationContext在 Service 方法中检查实际使用的 Endpoint 。当前. IncomingMessageHeaders

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

主机伪代码:

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"and"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

于 2012-06-12T12:35:30.880 回答
0

消息过滤器是要走的路。您可以使用“前缀”或创建自定义。

WCF 深度寻址

从文章的消息过滤器部分:

...它使用消息过滤器来确定匹配的端点(如果存在)。您可以选择使用哪个消息过滤器,也可以提供自己的过滤器。这种灵活性允许您在使用 Windows Communication Foundation 实现传统 SOAP 以外的事物时摆脱传统的调度模型 - 例如,此处描述的技术使您能够在 Windows Communication Foundation 消息传递基础上实现 REST/POX 样式的服务。

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

于 2012-06-13T16:16:50.140 回答