Why doesn't the IChannelFactory< TChannel> interface define a parameter-less CreateChannel()?
The concerete ChannelFactory< TChannel> class on the other hand does have a parameter-less CreateChannel().
For testability/SoC reasons I want to pass around IChannelFactory
interface but that forces me to also pass around an EndpointAddress
for use in CreateChannel(EndpointAddress)
.
As a workaround I have created a IChannelFactory2< IChannel>
which does have a parameter-less CreateChannel()
.
But ultimately I'm just curious as to why it was designed like this (generally WCF has reasonable design choices, but Im just too lazy to work this one out alone!)
The ChannelFactory<T>.CreateChannel() method is just a helper method, made possible by an implementation detail of the ChannelFactory<T> class.
If you look at the ChannelFactory<T> source code, you'll see this:
public TChannel CreateChannel()
{
return this.CreateChannel(this.CreateEndpointAddress(this.Endpoint), (Uri) null);
}
The CreateEndpointAddress
method is implemented internally by the abstract ChannelFactory class, which ChannelFactory<T> inherits from:
internal EndpointAddress CreateEndpointAddress(ServiceEndpoint endpoint)
{
if (endpoint.Address == (EndpointAddress) null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError((Exception) new InvalidOperationException(System.ServiceModel.SR.GetString("SFxChannelFactoryEndpointAddressUri")));
else
return endpoint.Address;
}
As you can see, the endpoint information is already available through the ChannelFactory<T>.Endpoint property, which is initialized through the various constructors of the ChannelFactory<T> class. These constructors, in fact, allow the consumers to specify the details of the endpoint to invoke.
Since interfaces cannot define constructors, the most appropriate way to pass that required piece of information is through the arguments of the method that is going to use it, that is the CreateChannel method.
I encountered the same problem.
My solution was using a factory pattern -
public interface IFactory<out T>
{
T CreateInstance();
}
public class WCFChannelFactory<TService> : IFactory<TService>
{
public ChannelFactory<TService> ChannelFactory { get; set; }
public WCFChannelFactory(ChannelFactory<TService> channelFactory)
{
ChannelFactory = channelFactory;
}
public TService CreateInstance()
{
return ChannelFactory.CreateChannel();
}
}
Then in my application I just use IFactory
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With