Providing custom context to your WCF service instance

In my last post about providing custom context I described a way that allowed you to scope the context to the operation/method level. This time I’m going to show you a way that will allow you to scope your context to the service instance level.

As you may, or may not, know there are a few instancing modes for WCF services. Per-Call, Per-Session, Shareable and Single. Not only that, but someone could technically invent their own mode of instancing by implementing a custom IInstanceContextProvider. Anyway, despite which mode is used, you may want to tie your custom context to the instance of the service and clean up when the instance is closed. Here’s what you’d need to do:

  1. Implement a custom IExtension<InstanceContext> which will contain the state of your custom context.
  2. Implement the IExtension<InstanceContext>::Attach and Detach like so:

    public void Attach(InstanceContext owner)
    {
        // ... implement your custom context setup code here ...

        // Hook up to the Closed event of the InstanceContext and call 
        // our Detach implementation so that we make sure to clean up
       
    owner.Closed += new EventHandler(delegate(object sender, EventArgs args)
        {
         
    this.Detach((InstanceContext)sender);
        });
    }

    public void Detach(InstanceContext owner)
    {
        // ... implement your custom context cleanup code here ...
    }

  3. Now we need a way to apply this extension, we need to create a custom attribute to apply some behavior.
  4. Implement IContractBehavior on this attribute and specifically implement IContractBehavior::ApplyDispatchBehavior (note: you can no-op all the other IContractBehavior methods) like so:

    public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
    {
        dispatchRuntime.InstanceContextInitializers.Add(
    this);
    }

  5. Implement IInstanceContextInitializer and specifically implement IInstanceContextInitializer::Initialze to apply your custom extension from Step 1 like so:

    public void Initialize(InstanceContext instanceContext, Message message)
    {
        instanceContext.Extensions.Add(
    new MyCustomExtension());
    }

This approach will guarantee that your custom context lives as long as your InstanceContext no matter what mode is used. If you wanted to get fancy you could combine all the functionality of my last post and this post into one attribute and extension implementation with a new property on the attribute that allows you to control whether you want your behavior custom context to apply to the InstanceContext or the OperationContext.

As far as how you expose your custom context (if it even needs to be exposed at all), you can provide a static “Current” property of your own which looks for the state in the extension using OperationContext.Current.InstanceContext.Extensions.Find<MyCustomExtension>().

Leave a Reply