Tuesday, June 1, 2010

Create WCF Proxies on the Fly

Here is one of the more useful classes i have used, it allows you to spin up a WCF proxy, and invoke any method from just the interface and a line of code.

Usage:
ChannelFactoryHelper.InvokeServiceMethod<IRoutingTopics>(
m => m.Method1(instruction, data), "Portal");


Class:

    public static class ChannelFactoryHelper
{
/// <summary>
/// Creates the channel.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
private static T CreateChannel<T>(string endpoint) where T : class
{
string endpointConfigName = endpoint;
try
{
ChannelFactory<T> factory = new ChannelFactory<T>(endpointConfigName);
return factory.CreateChannel();
}
catch (Exception ex)
{
throw new Exception(string.Format("Could not create proxy for endpoint configuration with name '{0}'", endpointConfigName), ex);
}
}

/// <summary>
/// Invokes the service method.
/// </summary>
/// <typeparam name="I"></typeparam>
/// <typeparam name="R"></typeparam>
/// <param name="source">The source.</param>
/// <returns></returns>
public static R InvokeServiceMethod<I, R>(Func<I, R> source, string endpointConfigName)
where I : class
{
R returnValue;
returnValue = InvokeServiceMethod<I, R>(source, CreateChannel<I>(endpointConfigName));
return returnValue;
}

/// <summary>
/// Invokes the service method.
/// </summary>
/// <typeparam name="I"></typeparam>
/// <param name="source">The source.</param>
public static void InvokeServiceMethod<I>(Action<I> source, string endpointConfigName)
where I : class
{
InvokeServiceMethod<I>(source, CreateChannel<I>(endpointConfigName));
}

/// <summary>
/// Invokes the service method.
/// </summary>
/// <typeparam name="I">Service Contract Interface.</typeparam>
/// <param name="source">The source.</param>
/// <param name="proxy">The proxy.</param>
private static void InvokeServiceMethod<I>(Action<I> source, I proxy) where I : class
{
try
{
// Call the service method
source.Invoke(proxy);
// Make sure to close the proxy
(proxy as IClientChannel).Close();
}
catch
{
if (proxy != null)
{
// If the proxy cannot close normally or an exception occurred, abort the proxy call
(proxy as IClientChannel).Abort();
}
throw;
}
}

/// <summary>
/// Invokes the service method.
/// </summary>
/// <typeparam name="I">Service Contract Interface.</typeparam>
/// <typeparam name="R">Return Type.</typeparam>
/// <param name="source">The source.</param>
/// <param name="proxy">The proxy.</param>
/// <returns></returns>
private static R InvokeServiceMethod<I, R>(Func<I, R> source, I proxy)
where I : class
{
R returnValue;
try
{
// Call the service method
returnValue = source.Invoke(proxy);
// Make sure to close the proxy
(proxy as IClientChannel).Close();
}
catch
{
if (proxy != null)
{
// If the proxy cannot close normally or an exception occurred, abort the proxy call
(proxy as IClientChannel).Abort();
}
throw;
}
return returnValue;
}
}