Created
March 17, 2015 10:42
-
-
Save a-h/c4fc17bafb8345e6ef1d to your computer and use it in GitHub Desktop.
ChannelFactory Cache and the Ninject Binding Extension Method
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Modified from examples at luisfsgoncalves.wordpress.com/2012/02/28/mixin-up-ninject-castle-dynamic-proxy-and-wcf-part-iii/ | |
// to use a channel factory cache. | |
public static class ToWcfClientExtensions | |
{ | |
public static IBindingWhenInNamedWithOrOnSyntax<T> ToWcfClient<T>(this IBindingToSyntax<T> syntax) where T : class | |
{ | |
return syntax.ToMethod(ctx => ctx.Kernel | |
.Get<ProxyGenerator>() | |
.CreateInterfaceProxyWithoutTarget<T>(new WcfProxyWithDisposalInterceptor<T>())); | |
} | |
} | |
public class WcfProxyWithDisposalInterceptor<TInterface> : IInterceptor where TInterface : class | |
{ | |
void IInterceptor.Intercept(IInvocation invocation) | |
{ | |
if (invocation.Method.Name.Equals("Dispose", StringComparison.Ordinal)) | |
{ | |
throw new InvalidOperationException("Dispose invoked on WcfProxyWithDisposalInterceptor"); | |
} | |
// I use a global ChannelFactory cache instead of caching using the Configuration System. | |
using (var channel = (IDisposable)ChannelFactoryCache.CreateChannel<TInterface>()) | |
{ | |
invocation.ReturnValue = InvokeMethod(invocation, channel, invocation.Arguments); | |
} | |
} | |
private static object InvokeMethod(IInvocation invocation, object channel, object[] arguments) | |
{ | |
try | |
{ | |
return invocation.Method.Invoke(channel, arguments); | |
} | |
catch (TargetInvocationException ex) | |
{ | |
// Preserve stack trace | |
var stackTrace = typeof(Exception).GetField("_remoteStackTraceString", BindingFlags.Instance | BindingFlags.NonPublic); | |
if (stackTrace != null) | |
{ | |
stackTrace.SetValue(ex.InnerException, ex.InnerException.StackTrace + Environment.NewLine); | |
} | |
throw ex.InnerException; | |
} | |
} | |
} | |
public static class ChannelFactoryCache | |
{ | |
private static Dictionary<Type, Tuple<EndpointAddress, object>> cache = new Dictionary<Type, Tuple<EndpointAddress, object>>(); | |
public static void Add<TInterface>(Uri uri, Binding binding, List<IEndpointBehavior> behaviors) | |
{ | |
var endpointAddress = new EndpointAddress(uri); | |
var factory = new ChannelFactory<TInterface>(binding); | |
if (behaviors != null) | |
{ | |
foreach (var behavior in behaviors) | |
{ | |
factory.Endpoint.Behaviors.Add(behavior); | |
} | |
} | |
if (!cache.ContainsKey(typeof(TInterface))) | |
{ | |
cache.Add(typeof(TInterface), new Tuple<EndpointAddress, object>(endpointAddress, factory)); | |
} | |
} | |
public static TInterface CreateChannel<TInterface>() where TInterface : class | |
{ | |
var data = cache[typeof(TInterface)]; | |
return (data.Item2 as ChannelFactory<TInterface>).CreateChannel(data.Item1) as TInterface; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment