2009-09-17 153 views
6

我们使用WCF在客户端和服务器应用程序之间进行通信。客户端应用程序有许多功能需要与服务器通信 - 我们选择在多个类中实现此功能(分离责任)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); 
      } 

线索是每客户端/服务器对的单个端点的配置,而不是每个服务接触的端点配置我想作用。

这可能吗?

回答

1

我怀疑这会起作用。 Xml序列化可能是这里最大的问题。

另外我不认为你真的需要它。如果我在你的鞋子里,我会尽量抽象与服务的沟通。基本上你总是会发送一个“消息”给服务,它有一个“目标”是你想要访问的类之一。该服务将始终以“响应”回复,其中内容将由“消息”发送到的类填充。

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

HTH。

+0

谢谢你的回复。序列化服务不是解决方案,服务上的方法需要在服务器上处理。参数需要是可序列化的,但方法本身必须在服务器上执行。我用一个SessionMode找到了一个关于ServiceContracts的文档,现在我正在尝试。 – Thies 2009-09-17 08:32:58

+0

我从来没有建议序列化服务。 Xml序列化是WCF的工作原理。它负责把你的对象和翻译成Xml和其他方式。 我的答复的重点是向您解释,包装您的服务请求和回复可能很好地解决了您的问题。 – 2009-09-18 08:08:55

3

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

这里是一个定义了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(); 
    } 
} 
+0

谢谢bobby,在你知道解决方案之前,定义一个问题并不总是很容易;)。如你所述;我有兴趣在同一个地址上托管多份合同 - 但最好还是在不同类别中实施服务。使用你的建议,我会有一个单独的“怪兽”类,通过在正确的非WCF服务上调用呼叫来实现所有服务 - 这是我想避免的。 – Thies 2009-09-17 08:49:38

+0

听起来很难实现你想要的一切。如果你希望客户端有一个很好的类型化契约,但你实际上并不希望你的服务类实现它们,那么你可能会写很多奇怪的通用消息处理代码,并重写WCF元数据行为, WSDL仍然可以生成。 – bobbymcr 2009-09-18 05:40:58

0

听起来像是你想保留你的单独服务,但有某种巴士,路线是经过。也许MSMQ,那么你可以有一个服务,每个消息弹出它到一个特定的队列,然后一个专用的服务可以读取那个特定的队列。

尽管承认不是一个基于WCF的解决方案。

由多个类实现的单个接口(读为ServiceContract)的概念将无法工作。所以你需要一个“怪物”服务来实现所有的服务,并且路由到正确的服务。门面模式涌入脑海。