Created
May 18, 2011 22:30
-
-
Save danielmarbach/979743 to your computer and use it in GitHub Desktop.
Client proxy interceptor for WCF and dynamic proxy
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
public class ClientProxyInterceptor : IInterceptor | |
{ | |
private readonly Func<ICommunicationObject> proxyCreator; | |
private readonly Type typeToProxy; | |
private ICommunicationObject proxyInstance; | |
public ClientProxyInterceptor(Func<ICommunicationObject> proxyCreator, Type typeToProxy) | |
{ | |
this.typeToProxy = typeToProxy; | |
this.proxyCreator = proxyCreator; | |
} | |
public ICommunicationObject CachedProxy | |
{ | |
get | |
{ | |
this.EnsureProxyExists(); | |
return this.proxyInstance; | |
} | |
set | |
{ | |
this.proxyInstance = value; | |
} | |
} | |
public void Intercept(IInvocation invocation) | |
{ | |
try | |
{ | |
invocation.ReturnValue = invocation.Method.Invoke(this.CachedProxy, invocation.Arguments); | |
} | |
catch (TargetInvocationException ex) | |
{ | |
Exception innerException = ex.InnerException; | |
throw innerException; | |
} | |
finally | |
{ | |
this.CloseProxy(invocation.Method); | |
} | |
} | |
private void EnsureProxyExists() | |
{ | |
if (this.proxyInstance == null) | |
{ | |
this.proxyInstance = this.proxyCreator(); | |
} | |
} | |
private void CloseProxy(MethodInfo methodInfo) | |
{ | |
var wcfProxy = this.CachedProxy; | |
if (wcfProxy != null && this.typeToProxy.IsAssignableFrom(methodInfo.DeclaringType)) | |
{ | |
if (wcfProxy.State == CommunicationState.Faulted) | |
{ | |
this.AbortCommunicationObject(wcfProxy); | |
} | |
else if (wcfProxy.State != CommunicationState.Closed) | |
{ | |
try | |
{ | |
wcfProxy.Close(); | |
this.CachedProxy = null; | |
} | |
catch (CommunicationException) | |
{ | |
this.AbortCommunicationObject(wcfProxy); | |
} | |
catch (TimeoutException) | |
{ | |
this.AbortCommunicationObject(wcfProxy); | |
} | |
catch (Exception) | |
{ | |
this.AbortCommunicationObject(wcfProxy); | |
throw; | |
} | |
} | |
} | |
} | |
private void AbortCommunicationObject(ICommunicationObject wcfProxy) | |
{ | |
wcfProxy.Abort(); | |
this.CachedProxy = null; | |
} | |
} |
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
public class ServicesInitializer | |
{ | |
public override void Start() | |
{ | |
foreach (Type serviceType in this.ServiceTypeProvider.Types) | |
{ | |
var binding = this.CreateBinding(); | |
var address = this.CreateEndpointAddress(serviceType); | |
var endpointAddress = new EndpointAddress(address); | |
var proxyCreatorType = this.MakeGenericType(serviceType); | |
var proxyCreator = this.GetProxyCreator(proxyCreatorType, binding, endpointAddress); | |
Type type = serviceType; | |
this.kernel.Bind(serviceType).ToMethod( | |
ctx => this.proxyGenerator.CreateInterfaceProxyWithoutTarget(type, new[] { typeof(IContextChannel), }, this.CreateInterceptor(proxyCreator, type))); | |
} | |
} | |
public override void Shutdown() | |
{ | |
foreach (IChannelFactory channelFactory in this.proxyInstanceCreatorCache.Values) | |
{ | |
channelFactory.Close(); | |
} | |
} | |
protected virtual IInterceptor CreateInterceptor(IChannelFactory proxyCreator, Type serviceType) | |
{ | |
dynamic channelFactory = proxyCreator; | |
return new ClientProxyInterceptor(() => (ICommunicationObject)channelFactory.CreateChannel(), serviceType); | |
} | |
protected virtual IChannelFactory CreateProxyInstanceCreator(Type genericProxyCreatorType, Binding binding, EndpointAddress endpointAddress) | |
{ | |
IChannelFactory proxyInstanceCreator = (IChannelFactory)Activator.CreateInstance(genericProxyCreatorType, binding, endpointAddress); | |
return proxyInstanceCreator; | |
} | |
private IChannelFactory GetProxyCreator(Type genericProxyCreatorType, Binding binding, EndpointAddress endpointAddress) | |
{ | |
IChannelFactory proxyInstanceCreator; | |
if (!this.proxyInstanceCreatorCache.TryGetValue(genericProxyCreatorType, out proxyInstanceCreator)) | |
{ | |
proxyInstanceCreator = this.CreateProxyInstanceCreator(genericProxyCreatorType, binding, endpointAddress); | |
this.proxyInstanceCreatorCache.Add(genericProxyCreatorType, proxyInstanceCreator); | |
} | |
return proxyInstanceCreator; | |
} | |
private Type MakeGenericType(Type serviceType) | |
{ | |
if (!serviceType.IsInterface) | |
{ | |
throw new InvalidOperationException("Type returned from proxy type provider must not be concrete type!"); | |
} | |
Type genericProxyType; | |
if (!this.genericTypeCache.TryGetValue(serviceType, out genericProxyType)) | |
{ | |
genericProxyType = typeof(ChannelFactory<>).MakeGenericType(new[] { serviceType }); | |
this.genericTypeCache.Add(serviceType, genericProxyType); | |
} | |
return genericProxyType; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment