简体   繁体   中英

WCF service returning another service (service factory?)

We are using WCF for communication between a client and a server application. The client application has many features that requires communication to the server - and we have chosen to implement this in multiple classes (seperation of responsability)

For the time, we are creating new WCF endpoints and service contracts for each object - Invoicing, Accounting, Content Management, etc. This causes a lot of endpoint configuration both on the client and server (with potential misconfiguration problems when moving into the test and production platforms).

I would like to know if I can define a single WCF endpoint that can deliver multiple service contact implementations. Our configuration files would then contain a single endpoint (to the service factory) and I can request different services by specifying the interface of the service I am interested in.

eg

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);
            }

The clue being a single endpoint configuration per client/server pair, instead of an endpoint configuration per service contact I would like to make available.

Is this possible?

I'm not 100% clear on what you're trying to do, but if you just want to be able to host different contracts on the same address with the implementation inside one service class, this is completely possible. To share an endpoint address, you must ensure that you use the same binding instance for each service endpoint.

Here is a complete sample which defines 3 contracts, 1 service class which implements all of them, and a ServiceHost with the 3 contract endpoints at the exact same address:

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();
    }
}

I doubt that this would work. Xml serialization might be the biggest problem here.

Also I don't think you actually need it. If I was in your shoes I would try and abstract my communication with the service. Basically you would always send a "Message" to the service, which has a "Target" being one of the classes you wanted to access. The service would always reply with a "Response", of which the contents would be filled by the class the "Message" was send to.

Another approach would be to route all these messages trough a service that would echo the request to the appropriate service. This way you keep scalability up, but it does still have a large configuration burden.

HTH.

Sounds like you want to keep your seperate services but have some kind of bus that routes is throught. MSMQ maybe, then you can have one services that takes every message pops it onto a specific queue and then a dedicated service can read that off that particular queue.

Not really a WCF based solution though admittedly.

The notion of a single interface(read as ServiceContract) implemented by multiple classes wont work. So you'd need one 'monster' service that implements all and routes through to the correct service. Facade pattern springs to mind.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM