Virtual Method Interception on Generic Delegates

Oct 20, 2011 at 3:10 PM

Hello Chaps,

I've got a bit of a problem and I wonder if anybody has come across this before.

I'm refactoring an existing application to make better use of Unity 2.0 and Enterprise Library 5.0, specifically I'm abstracting away hardcoded object validation and exception handling policy calls into configuration files.

The existing client application interacts with CRUD business objects (Providers) via a Facade layer composed of static methods.

I've amended the static methods to use a Unity factory to build these Providers and also I've set the Providers up take part in Interception for Validation and Exception Handling Policies.

This works great...

Static Facade using Unity to instantiate business objects

public static class ProductFacade
{
      public static Product GetProduct(int id)
      {
               var provider = UnityObjectFactory.CreateObject<ICrud<Product>>("ProductModel");
 
               return provider.Read(id);
      }
 
      public static void UpdateProduct(Product product)
      {
              var provider = UnityObjectFactory.CreateObject<ICrud<Product>>("ProductModel");
 
              provider.Update(product);
     }
}
 

Sample Unity policy and registration declarations

 
      <policy name="ModelValidationPolicy"> 
        <matchingRule name="ProductModelTypeName" type="TypeMatchingRule"> 
          <constructor>
            <param name="typeName" value="ProductModel" />
          </constructor>
        </matchingRule>
        <callHandler name="ProductRuleSet" type="Microsoft.Practices.EnterpriseLibrary.Validation.PolicyInjection.ValidationCallHandler, Microsoft.Practices.EnterpriseLibrary.Validation, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
          <constructor>
            <param name="ruleSet" value="Product Ruleset"/>
            <param name="specificationSource" value="Configuration"/>
          </constructor>
        </callHandler>
      </policy>
 
    <register name="ProductModel" type="ICrud`1[Product]" mapTo="ProductModel">
      <constructor>
        <param name="productRepository" dependencyName="ProductRepository" dependencyType="ProductRepository"></param>
      </constructor>
      <interceptor type="VirtualMethodInterceptor" />
      <interceptionBehavior type="PolicyInjectionBehavior"/>
    </register>
 

My problem is that I also need to attach Policies to the static methods.

So, I’ve written a thin wrapper class for the Facade to take Func and Action delegates to enable method interception…

public class CallWrapper

{

         public virtual TResult Invoke<T, TResult>(T x, Func<T, TResult> func)

                  where TResult

                  : class

         {

                  return func(x) as TResult;

         }

 

         public virtual void Invoke<T>(T x, Action<T> action)

         {

                  action(x);

         }

}

Configured it like this…

    <register name="CallWrapper" type="CallWrapper" mapTo="CallWrapper">

      <interceptor type="VirtualMethodInterceptor" />

      <interceptionBehavior type="PolicyInjectionBehavior"/>

    </register>

And called like this…

public void UpdateProduct(Product product)

{

         var wrapper = UnityObjectFactory.CreateObject<CallWrapper>("CallWrapper");

 

        wrapper.Invoke<Product>(product, ProductFacade.UpdateProduct);

}

 

 

Which generates a NullReferenceException on the Invoke call with a StackTrace of…

   at System.Configuration.ConfigurationElementCollection.BaseGet(Object key)

   at Microsoft.Practices.EnterpriseLibrary.Common.Configuration.NamedElementCollection`1.Get(String name)

   at Microsoft.Practices.EnterpriseLibrary.Validation.ConfigurationValidatorBuilder.GetTypeReference(Type type)

   at Microsoft.Practices.EnterpriseLibrary.Validation.ConfigurationValidatorBuilder.CreateValidator(Type type, String ruleset)

   at Microsoft.Practices.EnterpriseLibrary.Validation.ConfigurationValidatorFactory.InnerCreateValidator(Type targetType, String ruleset, ValidatorFactory mainValidatorFactory)

   at Microsoft.Practices.EnterpriseLibrary.Validation.ValidatorFactory.FindOrCreateValidator(ValidatorCacheKey cacheKey, Func`3 wrapAndInstrument)

   at Microsoft.Practices.EnterpriseLibrary.Validation.ValidatorFactory.CreateValidator(Type targetType, String ruleset)

   at Microsoft.Practices.EnterpriseLibrary.Validation.PolicyInjection.ValidationCallHandler.CreateValidator(Type type)

   at Microsoft.Practices.EnterpriseLibrary.Validation.PolicyInjection.ValidationCallHandler.CreateValidator(ParameterInfo parameter)

   at Microsoft.Practices.EnterpriseLibrary.Validation.PolicyInjection.ValidationCallHandler.Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)

   at Microsoft.Practices.Unity.InterceptionExtension.HandlerPipeline.Invoke(IMethodInvocation input, InvokeHandlerDelegate target)

   at Microsoft.Practices.Unity.InterceptionExtension.PolicyInjectionBehavior.Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)

   at Microsoft.Practices.Unity.InterceptionExtension.InterceptionBehaviorPipeline.Invoke(IMethodInvocation input, InvokeInterceptionBehaviorDelegate target)

Thanks if you’ve managed to make it to the bottom of this post and any ideas????

 

Oct 24, 2011 at 8:36 AM

Hi Paul,

Can you send me a project that demonstrates the problem?

 

Thanks,

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com