Developing Custom OperationInvoker

Posted: January 18, 2009 in Uncategorized, WCF
Tags: ,

In my earlier post I explained the different types of behaviors available in the WCF framework.In this post we will discuss about how to develop a custom operation invoker.Now the obvious question is what is an operation invoker.Operation invoker is the class responsible invoking the service method with a set of parameters and generate the output parameters and return value.The class responsible for this needs to implement the System.ServiceModel.Dispatcher.IOperationInvoker interface.This interface defines the following methods

  1. AllocateInputs – Returns an array of parameters required for the method call.
  2. Invoke – This method accepts the instance of the service object,array of parameter values ,array of output values as a parameters and returns the value returned by the service method.
  3. InvokeBegin – This is the asynchronous version of the Invoke method and initiates the call.
  4. InvokeEnd – This is the asynchronous version of the Invoke method and it completes the call.

Operation invoker is attached to the System.ServiceModel.DispatchOperation via the Invoker property.The default invoker provided by WCF framework for synchronous method call is System.ServiceModel.Dispatcher.SyncMethodInvoker.The custom invoker we are going to develop will be added to the DispatchOperation via Invoker property.

This custom invoker will provide a caching functionality.It will check that for a given set of parameters if output and return value exists in cache then it will use the cached values otherwise invoke the method and add results to cache.As a first step we will develop a class implementing IOperationBehavior and it will also wrap the instance of the default operation as shown below:

    public class CacheOperationInvoker:IOperationInvoker
    {
        /// <summary>
        /// This variable keeps a reference to the IOperationInvoker instance of DispatchOperation.
        /// </summary>
        private IOperationInvoker invoker;
        public CacheOperationInvoker(IOperationInvoker invoker)
        {
            this.invoker = invoker;
        }

    …………………
    }

We will now implement the logic to check from cache in the Invoke method as shown below:

public object Invoke(object instance, object[] inputs, out object[] outputs)
{

    //Generate Key method generates the key for cache store by concatenating the input params.
     string key = GenerateKey(inputs);

    //CacheOutput is a custom C# class that encapsulates the output parameter array and return value
     CacheOutput  item = null;
     object retval = null;
     outputs = null;
     if (!string.IsNullOrEmpty(key))
     {

        //Get from Cache
         item = CacheManager.GetItemFromCache(key) as CacheOutput ;
         if (item != null)
         {

            //return from Cache
             retval = item.ReturnValue;
             outputs = item.Outputs;
         }
         else
         {

            //Invoke the method using default invoker instance and set values in cache.
             retval = invoker.Invoke(instance, inputs, out outputs);
             item = new CacheOutput();
             item.Outputs = outputs;
             item.ReturnValue = retval;
             CacheManager.SetItemInCache(key, item);
         }
     }
     return retval;
}

Now we add a operation behavior and add our invoker to DispatchOperation as shown below:

public class CacheOperationBehavior:Attribute,IOperationBehavior
  {

      public void ApplyDispatchBehavior(OperationDescription operationDescription, System.ServiceModel.Dispatcher.DispatchOperation dispatchOperation)
      {
          //Get the instance of the default invoker
          IOperationInvoker invoker = dispatchOperation.Invoker;
          //Override with cache based invoker
          dispatchOperation.Invoker = new CacheOperationInvoker(invoker);
      }

  }

Finally the behavior can be added to the service as shown below:

[ServiceContract]
    public interface ICalculator
    {
        [OperationContract]
        [CacheOperationBehavior]
        int Add(int i, int j);
    }

The entire sample code can be found at:

http://code.msdn.microsoft.com/Project/Download/FileDownload.aspx?ProjectName=wcfsamples&DownloadId=4496

Comments
  1. Vaibhavi says:

    Hi all,

    I am working for a software integrator company. My projects includes working on Java

    and Ruby on Rails and Ajax. I think Web Services is really cool. We also recently

    have to now work on REST and they are talking about mashups and Struts. Can

    anyone tell me if there are some good training or conferences so that me and my team

    members can get to speed with these technologies. Learning from books is not my

    cup of tea, even not when I was doing engineering 😉

    All the help that group members can provide in this regard is much appreciated.

    Thanks,
    Vaibhaivi

  2. Anaz says:

    Hi Vaibhavi,

    There are several online resources available that you just google for. If any of your team like to read then quality books from wiley and oreilly cover such technologies in detail.

    I also highly recommend you could attend the upcoming Great Indian Developer Summit ( developersummit dot com) that is covering Java, Agile, REST, JAX-RS, mashups, .NET, Rich Web, JPA, SOA, rich user experiences, Spring, Groovy and more. They have most of the creators of these technologies as speakers. My team is attending this summit 22-25 apr at IISc campus where we are attending the web conference on April 23 and java on April 24. We have been able to get very good discounts. Maybe all those who are interested from your group can sign up together and get a good bargain from them. what say? I also attended last year’s conference and had a really cool time.

    In Hyderabad there is Sun Tech Days with some sun speakers.

    Thanks,
    Anaz

  3. Aaron says:

    Sankarsan, nice post. Because this is applied inside ApplyDispatchBehavior this is executing on the server side. Is there a similar intercept point on the client side where the service call could be short circuited at the proxy and fulfilled from cache on the client? The would be very valuable.

    – Aaron

    • sankarsan says:

      @Aaron thanks a lot for your comments.
      I think you cannot implement result caching in client side using similar technique because the ClientOperation does not expose any IOperationInvoker interface as property.
      The only way left is build a custom wrapper around your proxy and let the wrapper decide whether to invoke the operation or pick the results from cache.

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.