A Generic, IDisposable WCF Service Client
Posted
by Steve Wilkes
on Geeks with Blogs
See other posts from Geeks with Blogs
or by Steve Wilkes
Published on Thu, 30 Jun 2011 18:18:49 GMT
Indexed on
2011/07/01
0:22 UTC
Read the original article
Hit count: 473
WCF clients need to be cleaned up properly, but as they're usually auto-generated they don't implement IDisposable
. I've been doing a fair bit of WCF work recently, so I wrote a generic WCF client wrapper which effectively gives me a disposable service client.
The ServiceClientWrapper
is constructed using a WebServiceConfig
instance, which contains a Binding
, an EndPointAddress
, and whether the client should ignore SSL certificate errors - pretty useful during testing! The Binding
can be created based on configuration data or entirely programmatically - that's not the client's concern.
Here's the service client code:
using System;
using System.Net;
using System.Net.Security;
using System.ServiceModel;
public class ServiceClientWrapper<TService, TChannel> : IDisposable
where TService : ClientBase<TChannel>
where TChannel : class
{
private readonly WebServiceConfig _config;
private TService _serviceClient;
public ServiceClientWrapper(WebServiceConfig config)
{
this._config = config;
}
public TService CreateServiceClient()
{
this.DisposeExistingServiceClientIfRequired();
if (this._config.IgnoreSslErrors)
{
ServicePointManager.ServerCertificateValidationCallback =
(obj, certificate, chain, errors) => true;
}
else
{
ServicePointManager.ServerCertificateValidationCallback =
(obj, certificate, chain, errors) => errors == SslPolicyErrors.None;
}
this._serviceClient = (TService)Activator.CreateInstance(
typeof(TService),
this._config.Binding,
this._config.Endpoint);
if (this._config.ClientCertificate != null)
{
this._serviceClient.ClientCredentials.ClientCertificate.Certificate =
this._config.ClientCertificate;
}
return this._serviceClient;
}
public void Dispose()
{
this.DisposeExistingServiceClientIfRequired();
}
private void DisposeExistingServiceClientIfRequired()
{
if (this._serviceClient != null)
{
try
{
if (this._serviceClient.State == CommunicationState.Faulted)
{
this._serviceClient.Abort();
}
else
{
this._serviceClient.Close();
}
}
catch
{
this._serviceClient.Abort();
}
this._serviceClient = null;
}
}
}
A client for a particular service can then be created something like this:
public class ManagementServiceClientWrapper :
ServiceClientWrapper<ManagementServiceClient, IManagementService>
{
public ManagementServiceClientWrapper(WebServiceConfig config)
: base(config)
{
}
}
...where ManagementServiceClient
is the auto-generated client class, and the IManagementService
is the auto-generated WCF channel class - and used like this:
using(var serviceClientWrapper = new
ManagementServiceClientWrapper(config)
)
{
serviceClientWrapper.CreateServiceClient().CallService();
}
The underlying WCF client created by the CreateServiceClient()
will be disposed after the using
, and hey presto - a disposable WCF service client.
© Geeks with Blogs or respective owner