views:

584

answers:

3

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.

e.g.

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?

+1  A: 

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.

Jonathan van de Veen
Thank you for the reply. Serializing the service isn't a solution, the methods on the service need to be handled on the server. The parameters need to be Serializable, but the method itself must execute on the server. I have found a document about ServiceContracts with a SessionMode I am trying out now.
Thies
I never suggested serializing a service. Xml serialization is what makes WCF work. It is responsible for taking your objects and translating them into Xml and the other way around.The whole point of my reply is to explain to you that wrapping your service requests and replies may very well be a solution to your problem.
Jonathan van de Veen
+2  A: 

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();
    }
}
bobbymcr
Thank you bobby, it is not always easy to define a problem until you know the solution ;). As you state; I am interested in hosting many contracts on same address - but preferably have the service implementation in different classes as well. Using your suggestion I would have a single 'monster' class that implements all the services by proxing the calls on the correct non-WCF services - something I would like to avoid.
Thies
It sounds difficult to achieve all that you want. If you want the clients to have a nice typed contract, but you don't actually want your service class to implement all of them, you might be stuck writing lots of weird generic message processing code and overriding the WCF metadata behaviors so that a proper WSDL could still be generated.
bobbymcr
A: 

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.

MattC