Mike Nichols - Son of Nun Technology

So Many Tools...NAspect & Castle Windsor

I wanted to be able to catch any exceptions thrown in my IRepository<T> implementation that is using Castle Windsor to Inject at runtime. I could wrap each call to NHibernate methods with try..catch statements and pass any exceptions thru a exception handler to throw the new custom exception (PersistenceException) .

Or I could overarchitect my way into bliss :) I have been wanting to grow my AOP chops and had dorked around a bit with Aspect#. I like the AspectLang thing and I love how Castle is laid out, but that project is lagging behind (by their own admission) since the guys on it are so busy with the other projects. This is a place where it makes sense to help out on the project but I simply don't have the time to commit to it right now (if they'd have me anyways).

Aspect# (I think) doesn't fully support generics and I just had a hard time finding examples that were clear in getting up and running even in the tests for the scenarios I wanted to try out.

So I started poking around with NAspect, another Aspect Oriented Programming framework that is part of Mats Helander and company's Puzzle Framework. One thing I like about these guys' projects is they are just NICE in their forums. They really answer questions and have a sense of humor about it!

The first thing I noticed about the configuration setup is that it is real easy to get going. Plus I found tests that did exactly what I was looking to accomplish so that was bonus.

Here's what I wanted to do:  

        [Test, ExpectedException(typeof(PersistenceException))]

        public void InterceptExceptionWithNAspect_IoCUsedForInternalRepository_ThrowsPErsisteanceException()

        {

            IoC.Container.AddComponent("aspect",typeof(IRepository<>),typeof(FakeAspectRepository<>));

 

            IRepository<object> fromIoC = IoC.Resolve<IRepository<object>>("aspect");

 

            Assert.IsInstanceOfType(typeof(FakeAspectRepository<object>),fromIoC);

 

            Assert.IsInstanceOfType(typeof(FakeNHRepository<object>),((FakeAspectRepository<object>)fromIoC).Inner);

            object o = fromIoC.Get(1);

 

            Assert.IsNotNull(o);

 

        }

 

Basically I am adding a component to my IoC container (borrowed from Ayende) and get my injected FakeAspectRepository<T>.  My FakeAspectRepository simply decorates the FakeNHRepository<T> which we will proxy/intercept with NAspect:  

    public class FakeAspectRepository<T>: IRepository<T>

    {

        public FakeNHRepository<T> Inner

        {

            get { return _inner; }

        }

 

        private FakeNHRepository<T> _inner;

        public FakeAspectRepository()

        {

            Engine c = new Engine("AddException");

            c.Configuration.Aspects.Add(

                new SignatureAspect("PersistenceException", typeof(FakeNHRepository<object>), "*", new PersistenceInterceptor()));

 

 

            _inner = (FakeNHRepository<T>) c.CreateProxy(typeof (FakeNHRepository<T>));

 

        }

 

        public virtual T Get(object id)

        {

            return _inner.Get(id);

        }

...

...

 

What I want to happen is have my Get method throw an HibernateException and see if my PersistenceInterceptor catches it then throws its new PersistenceException. So here is my Interceptor:

    [IsRequired]

    [MayBreakFlow()]

    [ReplaceException(typeof(Exception), typeof(PersistenceException))]

    public class PersistenceInterceptor : IAroundInterceptor

    {

 

 

        public object HandleCall(MethodInvocation call)

        {

            MethodBase method = call.Method;

            object res = null;

            try

            {

                res = call.Proceed();

                Console.Write("BEFORE!!!");

            }

            catch (Exception ex)

            {

                Console.Write("AFTER");

                throw new PersistenceException();

            }

            return res;

 

        }

    }

 

My FakeNHRepository<T> just throws an exception: 

    public class FakeNHRepository<T> : IRepository<T>

    {

        public virtual T Get(object id)

        {

            throw new HibernateException("I'm not wearing any underwear.");

        }

Now I run my test and all happens as it should! I can now grow my interceptor to handle any exceptions that might occur in any method in my Repository implementation and then send those up to the next layer (after logging or whatever). One nice thing is that I can easily change this since I am using DI to inject my repositories into my code AND because I am indirectly using AOP to perform these stunts. To strip it out or change AOP providers would merely be a few small code changes. Any changes to exception handling can be in ONE PLACE.

Another thing is that this AOP solution seeems FAST. I was concerned that all this stuff going on for every DB call would be expensive, and it might turn out to be so, but really I haven't done any perf testing.