Based on answers by Marc Gravell, MichaelGG, and Matt Davis, our developers came up with the following:
public static class UsingServiceClient
{
public static void Do<TClient>(TClient client, Action<TClient> execute)
where TClient : class, ICommunicationObject
{
try
{
execute(client);
}
finally
{
client.DisposeSafely();
}
}
public static void DisposeSafely(this ICommunicationObject client)
{
if (client == null)
{
return;
}
bool success = false;
try
{
if (client.State != CommunicationState.Faulted)
{
client.Close();
success = true;
}
}
finally
{
if (!success)
{
client.Abort();
}
}
}
}
Example of use:
string result = string.Empty;
UsingServiceClient.Do(
new MyServiceClient(),
client =>
result = client.GetServiceResult(parameters));
It's as close to the "using" syntax as possible, you don't have to return a dummy value when calling a void method, and you can make multiple calls to the service (and return multiple values) without having to use tuples.
Also, you can use this with ClientBase<T>
descendants instead of ChannelFactory if desired.
The extension method is exposed if a developer wants to manually dispose of a proxy/channel instead.