Invoking the Policy Injection Application Block at WCF Service Boundaries

Back when we originally designed the Policy Injection Application Block for Enterprise Library 3.0, we made a conscious decision not to target the block at WCF service boundaries. This wasn't because we didn't think there was value at injecting cross-cutting concerns at service boundaries - in fact it's one of the most interesting places to do this. However we steered clear of this because WCF already has its own very powerful extensibility model that allows you to accomplish the same thing without using PIAB. In fact we exploited this in Enterprise Library with our Validation and Exception Shielding Behaviors. These behaviours plug in to the WCF pipeline and call the appropriate application blocks as requests come in to the service. We also built PIAB call handlers for these same blocks, but these were strictly for use beneath the service boundary.

However since rejoining the real world I've often wanted to apply PIAB handlers directly at WCF service boundaries. The main reason is that I want the exact same functionality as I'm using elsewhere in the application, and it seems like a waste of time to re-implement the same functionality using WCF Behaviors. Also because the Behavior extensibility model is so, well, extensive, I've found that it isn't as easy to build them as it is to build PIAB handlers.

So why can't you just apply PIAB policies on your service implementation class? Well you can - but remember that for any PIAB policies to take effect, you need to create or wrap your instances using the PolicyInjection.Create and Wrap methods. In most situations this isn't a big deal, but at WCF service boundaries you don't get this opportunity as the instances are created by WCF instead of by you. And so my policies were worthless.

Or so I thought - until I realised that the WCF Behaviors that I was trying to avoid were actually the key to getting what I wanted. It turns out that WCF lets you replace its implementation of IOperationInvoker (which is responsible for calling your service's methods) with your own implementation. In my case I simply build an implementation that wraps the service implementation class with a PIAB proxy before deferring to the original invoker. My implementation looks like this:

     public class PolicyInjectionInvoker : IOperationInvoker
    {
        private readonly IOperationInvoker _innerInvoker;
        private readonly Type _contractType;


        public PolicyInjectionInvoker(IOperationInvoker innerInvoker, Type contractType)
        {
            _innerInvoker = innerInvoker;
            _contractType = contractType;
        }

        #region IOperationInvoker Members

        public object[] AllocateInputs()
        {
            return _innerInvoker.AllocateInputs();
        }

        public object Invoke(object instance, object[] inputs, out object[] outputs)
        {
            PolicyInjector injector = (new PolicyInjectorFactory()).Create();

            object wrappedInstance = injector.Wrap(instance, _contractType);
            return _innerInvoker.Invoke(wrappedInstance, inputs, out outputs);
        }

        public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state)
        {
            PolicyInjector injector = (new PolicyInjectorFactory()).Create();
            object wrappedInstance = injector.Wrap(instance, _contractType);
            return _innerInvoker.InvokeBegin(wrappedInstance, inputs, callback, state);
        }

        public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result)
        {
            PolicyInjector injector = (new PolicyInjectorFactory()).Create();
            object wrappedInstance = injector.Wrap(instance, _contractType);
            return _innerInvoker.InvokeEnd(wrappedInstance, out outputs, result);
        }

        public bool IsSynchronous
        {
            get { return _innerInvoker.IsSynchronous;  }
        }

        #endregion
    }

You may have noticed that I'm using the PolicyInjector class rather than the usual PolicyInjection static façade. This was necessary since the PolicyInjection class uses generics, which requires knowing the target type at compile time. In this case I don't know the type, so I need to fall back to the old school non-generic version.

The next step is to tell WCF to plug my PolicyInjectionInvoker into my service's pipeline. This is where Behaviors come in. There are several types of Behaviors, but in this case I need to build an IOperationBehavior since that's the one that lets me replace the Invoker for any given operation. However Operation Behaviors need to be applied specifically to each operation. While this can be useful, in most cases I want to apply the same behaviours to all operations in my contract. To make this simpler I also decided to implement IContractBehavior to automatically apply the operation behaviour to all operations in my contract. My Behavior class looks like this:

     public class WrapForPolicyInjectionBehavior : Attribute, IOperationBehavior, IContractBehavior
    {
        #region IOperationBehavior Members

        public void AddBindingParameters(OperationDescription operationDescription, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {
        }

        public void ApplyClientBehavior(OperationDescription operationDescription, System.ServiceModel.Dispatcher.ClientOperation clientOperation)
        {
        }

        public void ApplyDispatchBehavior(OperationDescription operationDescription, System.ServiceModel.Dispatcher.DispatchOperation dispatchOperation)
        {
            
            dispatchOperation.Invoker = new PolicyInjectionInvoker(dispatchOperation.Invoker, operationDescription.DeclaringContract.ContractType);

        }

        public void Validate(OperationDescription operationDescription)
        {
        }

        #endregion

        #region IContractBehavior Members

        public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {
        }

        public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
        {
        }

        public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.DispatchRuntime dispatchRuntime)
        {

            foreach(OperationDescription opDescription in contractDescription.Operations)
            {
                opDescription.Behaviors.Add(this);
            }
        }

        public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
        {
        }

        #endregion
    }

As you can see, I only needed to implement the ApplyDispatchBehavior methods in this case, and the code is pretty trivial. All that remains now is to apply the behaviour to my service implementation class, like this:

     [WrapForPolicyInjectionBehavior]
    public class TestService : ITestService
    {
         // I could have put the [WrapForPolicyInjectionBehavior] attribute on specific operations instead

        [ExceptionCallHandler("Service Interface Policy")] // Or, apply policies using config if you prefer
        public bool DoStuff(string action)
        {
            // Do Stuff
        }

    }

That's all there is to it (but yes, I'll post this to EntLibContrib when I get time!). I'm also working on a new, improved exception shielding implementation built on PIAB. But that's a story for another day.