To intercept client-side calls, WCF provides the interface
IClientMessageInspector
, defined
as:
public interface IClientMessageInspector { object BeforeSendRequest(ref Message request,IClientChannel channel); void AfterReceiveReply(ref Message reply,object correlationState); }
The BeforeSendRequest()
method
is called just before the message is sent down the wire, allowing you to
affect the request message. Similarly, the AfterReceiveReply()
method is your chance to
interact with the reply message for post-call processing.
The client runtime represented by the ClientRuntime
class contains a collection of
message inspectors:
public sealed class ClientRuntime { public SynchronizedCollection<IClientMessageInspector> MessageInspectors {get;} //More members }
You can add your message inspector to the collection by
associating the proxy with an endpoint
behavior. That behavior needs to add the inspector in the
Apply
Client
Behavior()
method:
public interface IEndpointBehavior { void ApplyClientBehavior(ServiceEndpoint endpoint,ClientRuntime clientRuntime); //More members }
To encapsulate these steps I wrote the class InterceptorClientBase<T>
, defined in
Example E-4.
Example E-4. The InterceptorClientBase<T> class
public abstract class InterceptorClientBase<T> : ClientBase<T> where T : class { public InterceptorClientBase() { Endpoint.Behaviors.Add(new ClientInterceptor(this)); } public InterceptorClientBase(string endpointName) : base(endpointName) { Endpoint.Behaviors.Add(new ClientInterceptor(this)); } //More constructors protected virtual void PreInvoke(ref Message request) {} protected virtual void PostInvoke(ref Message reply) {} class ClientInterceptor : IEndpointBehavior,IClientMessageInspector { InterceptorClientBase<T> Proxy {get;set;} internal ClientInterceptor(InterceptorClientBase<T> proxy) { Proxy = proxy; } object IClientMessageInspector.BeforeSendRequest(ref Message request, IClientChannel channel) { Proxy.PreInvoke(ref request); return null; } void IClientMessageInspector.AfterReceiveReply(ref Message reply, object correlationState) { Proxy.PostInvoke(ref reply); } void IEndpointBehavior.ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { clientRuntime.MessageInspectors.Add(this); } //Rest of the implementation } }
InterceptorClientBase<T>
defines a nested private class called ClientInterceptor
that implements both
IEndpointBehavior
and
IClientMessageInspector
. The
constructors of InterceptorClientBase<T>
add an instance
of ClientInterceptor
to the proxy’s
collection of endpoint behaviors. Inside ClientInterceptor
, the implementation of
ApplyClientBehavior()
adds itself to
the collection of client runtime interceptors. Interceptor
Client
Base<T>
provides two virtual
methods, PreInvoke()
and Post
Invoke()
, for the use of derived
classes. The constructor of ClientInterceptor
takes a back reference to
the calling InterceptorClientBase<T>
, and it uses
that reference to call back to the PreInvoke()
and PostInvoke()
methods during the calls to
Before
SendRequest()
and AfterReceiveReply()
respectively.
3.16.130.201