ICallContextInitializer–How to capture the thread’s state?

Posted on January 14, 2011 by

0


The ICallContextInitializer located in System.ServiceModel.Dispatcher namespace is used to initialize and restore the thread context (thread local storage, CallContext, etc.) before and after the operation is invoked on the server side. By default, WCF will not do it for you unless you explicitly add this behavior.

ICallContextInitializer ‘s interface contains 2 methods, which allow the developer to interfere before and after the operation is executed:

public interface ICallContextInitializer
{
    object BeforeInvoke(InstanceContext instanceContext, IClientChannel channel, Message message);
    void AfterInvoke(object correlationState);
}

In BeforeInvoke you should capture the current state you are going to override, and return it for later use in the AfterInvoke method. The AfterInvoke method is called after invoking an operation, and it is provided with the correlationState argument which contains the returned captured state from the BeforeInvoke method.

ICallContextInitializer  is added to the CallContextInitializers on each operation through the IEndpointBehavior or through IOperationBehavior (see https://wcfpro.wordpress.com/2010/12/22/ioperationbehavior/).

    class MyCallContextInitializer : ICallContextInitializer
    {
        private const string c_contextKey = "__MY_CONTEXT_KEY_";

        public object BeforeInvoke(InstanceContext instanceContext, IClientChannel channel, Message message)
        {
            // Capture old state
            var oldState = CallContext.GetData(c_contextKey);
            // Set new context data
            CallContext.SetData(c_contextKey, channel.SessionId);
            // Return old state
            return oldState;
        }

        public void AfterInvoke(object correlationState)
        {
            // Restore context after invoke
            CallContext.SetData(c_contextKey, correlationState);
        }
    }

    class CallContextInitializerBehavior : IOperationBehavior
    {
        #region IOperationBehavior Members

        public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
        {
        }

        public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
        {
        }

        public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
        {
            dispatchOperation.CallContextInitializers.Add(new MyCallContextInitializer());
        }

        public void Validate(OperationDescription operationDescription)
        {
        }

        #endregion
    }

Advertisements
Posted in: WCF Extensions