2010
03.16

Once you’ve used svcutil to create proxy classes for a service (or created a Service Reference in Visual Studio), it’s often a bit of a pain to write the wrapper code that needs to instantiate the client, call the service operation, and close or abort the client as appropriate. So I wrote a generic ServiceClient class which will hopefully help to eliminate some boiler-plate code – it’s shown below.

/// <summary>
/// A WCF service client.
/// </summary>
/// <typeparam name="TContract">The type of the service contract.</typeparam>
internal class ServiceClient<TContract> : IDisposable
	where TContract : class
{
	/// <summary>
	/// The service client object.
	/// </summary>
	private TContract client;

	/// <summary>
	/// Initializes a new instance of the ServiceClient class.
	/// </summary>
	/// <param name="endpointName">The name of the endpoint to use.</param>
	public ServiceClient(string endpointName)
	{
		ChannelFactory<TContract> f = new ChannelFactory<TContract>(endpointName);
		this.client = f.CreateChannel();            
	}

	/// <summary>
	/// Calls an operation on the service.
	/// </summary>
	/// <typeparam name="TResult">The type of the object returned by the service operation.</typeparam>
	/// <param name="operation">The operation to call.</param>
	/// <returns>The results of the service operation.</returns>
	public TResult ServiceOperation<TResult>(Func<TContract, TResult> operation)
	{
		return operation(this.client);
	}

	/// <summary>
	/// Calls an operation on the service.
	/// </summary>
	/// <param name="operation">The operation to call.</param>
	public void ServiceOperation(Action<TContract> operation)
	{
		operation(this.client);
	}

	/// <summary>
	/// Disposes this object.
	/// </summary>
	public void Dispose()
	{
		try
		{
			if (this.client != null)
			{
				IClientChannel channel = this.client as IClientChannel;
				if (channel.State == CommunicationState.Faulted)
				{
					channel.Abort();
				}
				else
				{
					channel.Close();
				}
			}
		}
		finally
		{
			this.client = null;
			GC.SuppressFinalize(this);
		}
	}
}

With this class, you can call an operation SaveEmployee on a service with an IEmployeeService interface like this:

using (var client = new ServiceClient<IEmployeeService>("EmployeeEndpoint"))
{
	var response = client.ServiceOperation<EmployeeResponse>(
		c => c.SaveEmployee(request));
}

Wrapping the call in a using block means the client object is correctly closed and disposed, using the IDisposable interface. And if you’re calling an operation that doesn’t return anything, you can use the overload of ServiceOperation that takes in an Action.

1 comment so far

Add Your Comment
  1. Was looking for smth like that. Thanks.