While I am trying to learn WCF, and it seems straight-forward enough, I came through an odd situation…at least it seems odd to me.
Why is it that the ServiceHost ctor takes a concrete class, and the AddServiceEndpoint takes the Interface, and not vice versa? it seems the latter is more logical from an OOP standpoint.
Consider the following:
[ServiceContract]
interface IVocalAnimal
{
[OperationContract]
string MakeSound();
}
...
public class Dog : IVocalAnimal
{
public string MakeSound()
{
return("Woof!");
}
}
...
public class Cat : IVocalAnimal
{
public string MakeSound()
{
return("Meeooow!");
}
}
So now we wanto create an “AnimalSound” service that you can connect to get the sound of a Dog or a Cat via /AnimalSoundService/Dog or /AnimalSoundService/Cat
...
Uri baseAddress = new Uri("net.pipe://localhost/AnimalSoundService");
ServiceHost serviceHost = new ServiceHost(typeof(IVocalAnimal), baseAddress);
serviceHost.AddServiceEndpoint(typeof(Dog), new NetNamedPipeBinding(NetNamedPipeSecurityMode.None), "Dog");
serviceHost.AddServiceEndpoint(typeof(Cat), new NetNamedPipeBinding(NetNamedPipeSecurityMode.None), "Cat");
...
But the above code will not compile as for some reason(s) I don’t quite understand, the ServiceHost ctor wants the concrete class (so either Dog or Cat) and the EndPoint wants the Interface.
So what is the reason it is not vice-versa as it seems to me more natural that the finer granularity endpoint supports a specific implementation (so you could hit specific implementations of the contract per endpoint address) while the more general ServiceHost should be the one to accept the interface?
Btw, I am not being pedantic..I am just honestly trying to understand as I am sure it is I that missed something here.
When you create the ServiceHost, you are creating the actual service, so it must be concrete.
Your endpoints, on the other hand, are what your clients see. You don’t necessarily want your clients to know your implementation — they should just get the interface definition.
The endpoind DOES support a specific implementation, as you say: whichever one you use when you create the ServiceHost. The purpose of endpoints, is not to provide multiple implementations, but to provide multiple protocols/bindings to access a single implementation.
If you want distinct Dog and Cat services, I believe you’ll need two ServiceHosts, each with one NetNamedPipeBinding endpoint.