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
- AllocateInputs – Returns an array of parameters required for the method call.
- 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.
- InvokeBegin – This is the asynchronous version of the Invoke method and initiates the call.
- 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