CustomAttributeMatchingRule: Creating a interceptor Handler Attribute and applaying it to many "unity registered types"

May 11, 2010 at 5:05 PM
Edited May 11, 2010 at 5:11 PM

Hello all, I´m pretty new to unity but not to other AOP/DI frameworks. [Note: we are using EL5.0/Unity 2.0 over 3.5 .NET]

We are trying to create a spring.net like aspect to implement transaction management arround methods anotated with the [Transaction] attibute.

The purpose of it is to programatically anotate or decorate the methods that will open/close session/transactions and in case to rollback. So far we are able to achieve it creating the next infraestrucure

1. A class that implements the HandlerAttribute and a TransactionCallHandler that implements ICallHandler

 

namespace DocumentVerifiers.Common.Interceptors
{
    [AttributeUsage(AttributeTargets.Method)]
    public class TransactionAttribute : HandlerAttribute
    {
        public override ICallHandler CreateHandler(IUnityContainer container)
        {
            return new TransactionCallHandler();
        }
    }
} 

 

 

public class TransactionCallHandler : ICallHandler
    {
        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
        {
            Console.WriteLine("INTERCEPTOR START");
            IMethodReturn returnMessage = getNext()(input, getNext);
            if (returnMessage.Exception != null)
            {
                Console.WriteLine("EXCEPTION!!... " + returnMessage.Exception);
            }
            Console.WriteLine("INTERCEPTOR END");
            return returnMessage;
        }

        public int Order { get; set; }

    }

   3. A xml unity container configured as follows

  <unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
    <sectionExtension prefix="" type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration"/>
    <container name="container">
      <extension type="Interception"/>
      <interception >
      </interception>      
      <register name="SessionProvider"
                type="DocumentVerifiers.Repository.ISessionProvider, DocumentVerifiers.Repository"
                mapTo="DocumentVerifiers.Repository.SessionProvider, DocumentVerifiers.Repository">
      <lifetime type="singleton"/>
      </register>
      <register name="PersonRepository"
                type="DocumentVerifiers.Repository.Interfaces.IPersonRepository, DocumentVerifiers.Repository"
                mapTo="DocumentVerifiers.Repository.Repositories.PersonRepository, DocumentVerifiers.Repository">
        <lifetime type="singleton"/>
        <property dependencyName="SessionProvider" name="SessionProvider"></property>
      </register>
      <register name="PersonService"
                type="DocumentVerifiers.Services.Interfaces.IPersonService, DocumentVerifiers.Services"
                mapTo="DocumentVerifiers.Services.Services.PersonService, DocumentVerifiers.Services">
        <lifetime type="singleton"/>
        <property dependencyName="PersonRepository" name="PersonRepository"></property>
        <interceptor type="TransparentProxyInterceptor"/>
        <policyInjection/>
      </register>
    </container>
  </unity>

Thats brilliant!! Unity intercept the call where the annotations are placed (inside PersonService) and execute the statements placed inside TransactionCallHandler.Invoke The point here is that we need to include the statements <interceptor type="TransparentProxyInterceptor"/><policyInjection/> for each class or service that want to use the annotation [Transacion]

We are sure that there will be other ways to do it automatically without the need of include <interceptor type="TransparentProxyInterceptor"/><policyInjection/> for every single annotated class that wanto to use declarative transacion management.

Dont ask me why but we guess that just adding something like this, could work

     <interception >
        <policy name="InterceptionPolicy">
          <matchingRule name="Rule" type="CustomAttributeMatchingRule">
            <constructor>
              <param name="attributeType" type="Type" value="DocumentVerifiers.Common.Interceptors.TransactionAttribute, DocumentVerifiers.Common">
                </param>
              <param name="inherited" type="bool" value="true"/>
            </constructor>
          </matchingRule>
        </policy>
      </interception>    


But unfortunately the next exception is raised "System.InvalidOperationException: The type name or alias Type could not be resolved. Please check your configuration file and verify this type name.."

We are not sure if we are in the right direction and need some guidance. I´m sure that you are pretty bussy and wanna thank you in advance.

[Note: we are using EL5.0/Unity 2.0 over 3.5 .NET]

Jacobo