inheritanceunity-containerpolicy-injection

Unity Interception in Derived Class


I've got a situation where policy injection no longer works when I'm using a derived class.

The classes involved look like this (basically an interface, an abstract base class, and an implementation class):

public interface IRepository<T>
{
    void Create(T iItem);
}

public abstract class ElmtRepository<T> : IRepository<T>
{
    protected List<T> Items { get; set; }

    public ElmtRepository()
    {
        Items = new List<T>();
    }

    public void Create(T iItem)
    {
        Items.Add(iItem);
    }
}

public class AcctPgmRepository : ElmtRepository<AcctPgm>
{
}

The configuration looks like this:

  <container>
    <extension type="Interception"/>
    <register type="IRepository[AcctPgm]" mapTo="AcctPgmRepository">
      <interceptor type="InterfaceInterceptor"/>
      <interceptionBehavior type="PolicyInjectionBehavior"/>
    </register>
    <interception>
      <policy name="policy-create">
        <matchingRule name="create-rule1" type="TypeMatchingRule">
          <constructor>
            <param name="typeName">
              <value value="AcctPgmRepository"/>
            </param>
          </constructor>
        </matchingRule>
        <matchingRule name="create-rule2" type="MemberNameMatchingRule">
          <constructor>
            <param name="namesToMatch">
              <array type="string[]">
                <value value="Create"/>
              </array>
            </param>
          </constructor>
        </matchingRule>
        <callHandler name="create-handler1" type="AcctPgmAuthorizationHandler">
          <lifetime type="singleton"/>
          <constructor>
            <param name="allowedRoles">
              <array type="string[]">
                <value value="GroupController"/>
              </array>
            </param>
          </constructor>
        </callHandler>
      </policy>
    </interception>
  </container>

If I remove the ElmtRepository base class, it works as expected. With the base class, the injection doesn't happen. No error messages, but no policies either. This happens even if I implement the Create() method in the derived class.

Is there a way to make this sort of class hierarchy work with Unity policy injection?

Thanks, Jim


Solution

  • This kind of class inheritance Unity usually does without a problem. However configuring generics is endless headaches with poor error messages. I bet that’s your real problem. However since you didn’t post your error message (or the AcctPgm class, or the AcctPgmAuthorizationHandler) I can’t be sure.

    I changed the contained type to int and got this version of your code working:

    using System;
    using System.Collections.Generic;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using Microsoft.Practices.Unity.InterceptionExtension;
    using Microsoft.Practices.Unity;
    using Microsoft.Practices.Unity.Configuration;
    
    namespace UnityTest
    {
        public interface IRepository<T>
        {
            void Create(T iItem);
        }
    
        public abstract class ElmtRepository<T> : IRepository<T>
        {
            protected List<T> Items { get; set; }
    
            public ElmtRepository()
            {
                Items = new List<T>();
            }
    
            public void Create(T iItem)
            {
                System.Diagnostics.Debug.WriteLine("Creating...");
                Items.Add(iItem);
            }
        }
    
        public class AcctPgmRepository : ElmtRepository<int> { }
    
        public class LogHandler : ICallHandler
        {
            public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
            {
                System.Diagnostics.Debug.WriteLine("Begin");
                IMethodReturn result = getNext().Invoke(input, getNext);
                System.Diagnostics.Debug.WriteLine("End");
                return result;
            }
            public int Order { get; set; }
        }
    
        [TestClass]
        public class InheritenceGenericsTests
        {
            [TestMethod]
            public void CreateTest()
            {
                IUnityContainer container = new UnityContainer().LoadConfiguration("Inheritence");
                IRepository<int> r2 = container.Resolve<IRepository<int>>();
                Assert.IsNotNull(r2);
                r2.Create(2);
            }
        }
    }
    

    with config:

    <alias alias="IRepository" type="UnityTest.IRepository`1, UnityTest"/>
    <alias alias="IRepositoryClosed" type="UnityTest.IRepository`1[System.Int32], UnityTest"/>
    <alias alias="AcctPgmRepository" type="UnityTest.AcctPgmRepository, UnityTest"/>
    
    <container name="Inheritence">
      <extension type="Interception"/>
      <!-- register either type="IRepositoryClosed" or type="IRepository" -->
      <register type="IRepositoryClosed" mapTo="AcctPgmRepository">
        <interceptor type="InterfaceInterceptor"/>
        <policyInjection/>
      </register>
      <interception>
        <policy name="policy-create">
          <matchingRule name="create-rule2" type="MemberNameMatchingRule">
            <constructor>
              <param name="namesToMatch">
                <array type="string[]">
                  <value value="Create"/>
                </array>
              </param>
            </constructor>
          </matchingRule>
          <callHandler name="create-handler1" type="UnityTest.LogHandler, UnityTest"></callHandler>
        </policy>
      </interception>
    </container>
    

    Gives output:

    Begin
    Creating...
    End