Lowterm
Lowterm

Reputation: 101

What's the difference between ChannelFactory<T> and ClientBase<T>

can you explain to me please, What's the difference between ChannelFactory and ClientBase and which of them is better to use for a SelfHost Client-Server Apllication.

using(ChannelFactory<MyInterface> cf = new ChannelFactory<MyInterface>("Endpoint From Web.Config")){} 

public class MyClient : ClientBase<MyInterface>, MyInterface {}

Thanks

Upvotes: 2

Views: 1344

Answers (1)

Wiktor Zychla
Wiktor Zychla

Reputation: 48250

Let's have an interface that defines the contract:

[ServiceContract]
public interface TheInterface
{
    [OperationContract]
    string DoWork( string Work );
}

The ChannelFactory automatically creates a proxy that only implements the interface.

 var factory = new ChannelFactory<TheInterface>( new BasicHttpBinding() );
 var address = new EndpointAddress( "http://..." );
 var client = factory.CreateChannel( address );

 // there are no other methods on the "client" reference
 // than the interface's DoWork method
 client.DoWork( "foo" );

On the other hand, a class that inherits from the ClientBase not only implements the interface but also exposes multiple additional properties that can be used to alter the behavior of the client.

public class TheInterfaceProxy : ClientBase<TheInterface>, TheInterface
{
    public TheInterfaceProxy( Binding binding, EndpointAddress address ) : base( binding, address ) { }

    public string DoWork( string Work )
    {
        return this.Channel.DoWork( Work );
    }
}

And then

var address = new EndpointAddress( "http://..." );

using ( var client = new TheInterfaceProxy( new BasicHttpBinding(), address ) )
{
     // DoWork is here
     // but multiple other members are there too
     // for example - applying a custom endpoint behavior:
     client.Endpoint.EndpointBehaviors.Add( new InspectorBehavior() );

     client.DoWork( "bar" );
}

where an example simple behavior is used to inspect incoming/outgoing messages at the client side

class InspectorBehavior : IEndpointBehavior
{
    #region IEndpointBehavior Members

    public void AddBindingParameters( ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters )
    {
    }

    public void ApplyClientBehavior( ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime )
    {
        clientRuntime.ClientMessageInspectors.Add( new DispatchInspector() );
    }

    public void ApplyDispatchBehavior( ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher )
    {
    }

    public void Validate( ServiceEndpoint endpoint )
    {
    }

    #endregion
}

class DispatchInspector : IClientMessageInspector
{
    #region IClientMessageInspector Members

    public void AfterReceiveReply( ref Message reply, object correlationState )
    {
        MessageBuffer buffer = reply.CreateBufferedCopy( Int32.MaxValue );
        reply = buffer.CreateMessage();
        Console.WriteLine( "Receiving:\n{0}", buffer.CreateMessage().ToString() );
    }

    public object BeforeSendRequest( ref Message request, IClientChannel channel )
    {
        MessageBuffer buffer = request.CreateBufferedCopy( Int32.MaxValue );
        request = buffer.CreateMessage();
        Console.WriteLine( "Sending:\n{0}", buffer.CreateMessage().ToString() );

        return null;
    }

    #endregion
}

There is no answer to which is better, however:

  • if you don't need anything but the default behavior - you can stick with the ChannelFactory, it's the simplest of the two
  • for anything extra, use the ClientBase, it requires an extra class, though

Upvotes: 2

Related Questions