EntLib PolicyInjection, Caching and WCF Services

EntLib, Readify, WCF 5 Comments

PolicyInjection on WCF Services

Yesterday I’ve worked on writing a nice and quick Dynamic WCF Client Proxy using code emitting. Today I’d like to use this together with EntLib 3.1 Policy Injection and Caching Application Block to cache WCF calls and avoid extra calls if they are requested by the application within a specific amount of time.

The simple way to achieve this is by simply changing the GetInstance method of the WCFClientProxy.cs to:

/// <summary>
/// Returns a new instance for a client proxy over the specified interface with the specified config name used for initialization.
/// </summary>
public static TInterface GetInstance(string configName)
{
    // Build the type
    ClassBuilder<TInterface> builder = new ClassBuilder<TInterface>();
    Type type = builder.GenerateType();

    // Create new instance
    TInterface instance = (TInterface)Activator.CreateInstance(type, new object[] { configName });

    // Wrap it in the Policy Injection
    return PolicyInjection.Wrap<TInterface>(instance);
}

Adding Caching Application Block on the WCF service

Using our new WCFClientProxy class, write a quick config file:

<configSections>
    <section name="policyInjection" type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.Configuration.PolicyInjectionSettings, Microsoft.Practices.EnterpriseLibrary.PolicyInjection, Version=3.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
</configSections>

<policyInjection>
    <policies>
        <add name="IService1Policy">
            <matchingRules>
                <add type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.MatchingRules.MemberNameMatchingRule, Microsoft.Practices.EnterpriseLibrary.PolicyInjection, Version=3.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" name="Member Name Matching Rule">
                    <matches>
                        <add match="MyOperation1"/>
                    </matches>
                </add>
                <add type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.MatchingRules.TypeMatchingRule, Microsoft.Practices.EnterpriseLibrary.PolicyInjection, Version=3.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" name="Type Matching Rule">
                    <matches>
                        <add match="IService1"/>
                    </matches>
                </add>
            </matchingRules>
            <handlers>
                <add expirationTime="00:00:10"  type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.CallHandlers.CachingCallHandler, Microsoft.Practices.EnterpriseLibrary.PolicyInjection.CallHandlers, Version=3.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" name="Caching Call Handler"/>
            </handlers>
        </add>
    </policies>
</policyInjection>

To ask the PolicyInjection to load the CachingCallHandler on our method (IService1.MyOperation1) and cache for no more than 10 seconds.

Write a quick test for the above code:

IService1 service = WCFClientProxy<IService1>.GetInstance("Service1");

Random rand = new Random(7);

for (int i = 0; i < 10; i++)
{
    Console.WriteLine(i + " " + DateTime.Now.ToString("HH:MM:ss:ffff") + " result -> " + service.MyOperation1("a", 0));
    Thread.Sleep(1000 * rand.Next(20));
}

Our server implementation simply returns the time the server has when the call was made.

And give it a try to prove it’s working:

First two calls (0 and 1 with red) share the same “10 seconds” limit defined for the Caching Handler and we can see that even if we called the server twice the same result was returned telling us the Caching Handler kicked in and we avoided the call to the server.

The second and third call (1 and 2 with blue) were done at more than 10 seconds difference and we can see the server was called and it returned a new time.

Quick, simple and easy. No code, no bugs.

If you like EntLib with this code you would achive more or less the same as Glav’s WCF Services Caching without having to roll your own Caching implementation.