【问题标题】:WCF service returning another service (service factory?)WCF 服务返回另一个服务(服务工厂?)
【发布时间】:2009-09-17 08:14:08
【问题描述】:

我们使用 WCF 在客户端和服务器应用程序之间进行通信。客户端应用程序具有许多需要与服务器通信的功能 - 我们选择在多个类中实现这一点(职责分离)

目前,我们正在为每个对象创建新的 WCF 端点和服务合同 - 发票、会计、内容管理等。这会导致客户端和服务器上的大量端点配置(移动时可能会出现配置错误的问题)测试和生产平台)。

我想知道我是否可以定义一个可以提供多个服务联系实现的单个 WCF 端点。然后我们的配置文件将包含一个端点(到服务工厂),我可以通过指定我感兴趣的服务的接口来请求不同的服务。

例如

using (IServiceClientFactory serviceClientFactory = new RealProxyServiceClientFactory())
            {
                // This is normal WCF proxy object creation.
                IServiceFactory serviceFactory = serviceClientFactory.CreateInstance<IServiceFactory>("");

                // This is what we would like to do
                IInvoiceService invoiceService = serviceFactory.getService(typeof(IInvoiceService));

                invoiceService.executeOperation(data);
            }

线索是每个客户端/服务器对的单个端点配置,而不是我希望提供的每个服务联系人的端点配置。

这可能吗?

【问题讨论】:

    标签: c# .net wcf endpoints


    【解决方案1】:

    我不是 100% 清楚你想要做什么,但如果你只是希望能够在同一个地址上托管不同的合约,并在一个服务类中实现,这是完全可能的。要共享端点地址,您必须确保为每个服务端点使用相同的绑定实例。

    这是一个完整的示例,它定义了 3 个合约、1 个实现所有这些合约的服务类,以及一个具有完全相同地址的 3 个合约端点的 ServiceHost:

    using System;
    using System.ServiceModel;
    
    [ServiceContract]
    interface IContractA
    {
        [OperationContract]
        void A();
    }
    
    [ServiceContract]
    interface IContractB
    {
        [OperationContract]
        void B();
    }
    
    [ServiceContract]
    interface IContractC
    {
        [OperationContract]
        void C();
    }
    
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    class Service : IContractA, IContractB, IContractC
    {
        public Service()
        {
        }
    
        public void A()
        {
            Console.WriteLine("A");
        }
    
        public void B()
        {
            Console.WriteLine("B");
        }
    
        public void C()
        {
            Console.WriteLine("C");
        }
    }
    
    class Program
    {
        public static void Main(string[] args)
        {
            Uri address = new Uri("net.pipe://localhost/Service/");
            ServiceHost host = new ServiceHost(new Service(), address);
            NetNamedPipeBinding binding = new NetNamedPipeBinding();
            host.AddServiceEndpoint(typeof(IContractA), binding, string.Empty);
            host.AddServiceEndpoint(typeof(IContractB), binding, string.Empty);
            host.AddServiceEndpoint(typeof(IContractC), binding, string.Empty);
            host.Open();
    
            IContractA proxyA = ChannelFactory<IContractA>.CreateChannel(new NetNamedPipeBinding(), new EndpointAddress(address));
            proxyA.A();
            ((IClientChannel)proxyA).Close();
    
            IContractB proxyB = ChannelFactory<IContractB>.CreateChannel(new NetNamedPipeBinding(), new EndpointAddress(address));
            proxyB.B();
            ((IClientChannel)proxyB).Close();
    
            IContractC proxyC = ChannelFactory<IContractC>.CreateChannel(new NetNamedPipeBinding(), new EndpointAddress(address));
            proxyC.C();
            ((IClientChannel)proxyC).Close();
    
            host.Close();
        }
    }
    

    【讨论】:

    • 谢谢你,鲍比,在你知道解决方案之前,定义问题并不总是那么容易;)。正如你所说;我有兴趣在同一个地址上托管许多合同——但最好也有不同类的服务实现。使用您的建议,我将有一个“怪物”类,通过代理正确的非 WCF 服务上的调用来实现所有服务——我想避免这种情况。
    • 听起来很难达到你想要的一切。如果您希望客户端有一个很好的类型化合同,但您实际上并不希望您的服务类实现所有这些,您可能会被困在编写大量奇怪的通用消息处理代码并覆盖 WCF 元数据行为,以便一个适当的仍然可以生成 WSDL。
    【解决方案2】:

    我怀疑这会奏效。 Xml 序列化可能是这里最大的问题。

    另外,我认为您实际上并不需要它。如果我处于你的位置,我会尝试抽象我与服务的通信。基本上,您总是会向服务发送“消息”,该服务的“目标”是您想要访问的类之一。该服务将始终以“响应”进行回复,其内容将由“消息”发送到的类填充。

    另一种方法是将所有这些消息通过一个服务路由,该服务会将请求回显到适当的服务。这样可以保持可扩展性,但仍然有很大的配置负担。

    HTH。

    【讨论】:

    • 感谢您的回复。序列化服务不是解决方案,服务上的方法需要在服务器上处理。参数需要可序列化,但方法本身必须在服务器上执行。我找到了一个关于 ServiceContracts 的文档,我现在正在尝试使用 SessionMode。
    • 我从不建议序列化服务。 Xml 序列化是 WCF 工作的原因。它负责获取您的对象并将它们转换为 Xml,反之亦然。我的回复的全部目的是向您解释,包装您的服务请求和回复很可能是您问题的解决方案。
    【解决方案3】:

    听起来您想保留单独的服务,但有某种路线经过的公共汽车。也许是 MSMQ,然后您可以拥有一个服务,将每条消息弹出到特定队列中,然后专用服务可以从该特定队列中读取该消息。

    诚然,这并不是一个真正基于 WCF 的解决方案。

    由多个类实现的单个接口(读作 ServiceContract)的概念是行不通的。所以你需要一个“怪物”服务来实现所有并路由到正确的服务。立面图案浮现在脑海中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-31
      • 1970-01-01
      • 1970-01-01
      • 2018-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多