VirtualMethodInterceptor for derived classes - possible?

Dec 15, 2008 at 8:26 PM
Hi All,

I wanted that VirtualMethodInterceptor was applied to derived classes without having specifically configure interception for each new derived class. In order to achieve that I tried to do the following:

  • Configure interception for the base class
  • Register derived class as base class mapped  to the actual derived class

Seems pretty straightforward but for some reason this does not work - the call handler is not called :(

Am I doing something wrong?

Here is the code:

Test method:
[TestMethod]
public void ShouldAttachToDerivedAsBase()
{
 // class registering
 IUnityContainer container = new UnityContainer();
 container.RegisterType<Base>("Base", new InjectionMember[] { });
 container.RegisterType<Base, Derived>("Derived", new InjectionMember[] { });
 container.RegisterType<ICallHandler, CallCountHandler>("Counter", new InjectionMember[] { });

 // interception configuration
 container.AddNewExtension<Interception>();
 Interception interception = container.Configure<Interception>();
 string registrationName = "Derived";
 interception.SetInterceptorFor(typeof(Base), registrationName, new VirtualMethodInterceptor());
 PolicyDefinition vmPolicy = interception.AddPolicy("VirtualMethod");
 vmPolicy.AddMatchingRule<MemberNameMatchingRule>(new InjectionMember[] { new InjectionConstructor("VirtualMethod", true) });
 CallCountHandler counter = new CallCountHandler();
 container.RegisterInstance<ICallHandler>("Counter", counter);
 vmPolicy.AddCallHandler("Counter");

 // test
 Base instance = container.Resolve<Base>(registrationName);
 instance.VirtualMethod();
 Assert.AreEqual(1, counter.Count); // Count property returns  the numer of calls to the handler Invoke method
}

Classes:
public class Base
{
 public virtual void VirtualMethod()
 {
  Console.WriteLine("Base");
 }
}
public class Derived : Base
{
 public override void VirtualMethod()
 {
  Console.WriteLine("Derived");
  base.VirtualMethod();
 }
}

CallCountHandler Invoke:
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
 ++m_count;
 IMethodReturn result = getNext().Invoke(input, getNext);
 return result;
}

If I change registrationName  to "Base" forcing instantiation of the Base class instead of Derived it works, but it is not exactly waht I am looking for. Any suggestions?


  

Dec 16, 2008 at 5:55 AM
"Am I doing something wrong?"

Yes. The container doesn't work that way. Other than type mapping, configuration is only applied based on the concrete class being resolved. So it will look for configuration for Derived only at the time it is building up a Derived object. Base is a different class, so it doesn't affect the operation of the container.