Search code examples
c#castle-dynamicproxy

Using Castle to create AOP with a 3rd party IoC


I am trying to use aspect oriented programming. The problem is that there is a custom IoC built in house that does not support this type of programming. I broke the problem down into the most important pieces. I am using castle to achieve AOP. The problems are described in the code comments.

I don't think I can do this given generics are intended to be known at compile time. However, I'm hoping the community can outsmart me.

UPDATE 2 - Updated to working code (this is thanks to @vasiloreshenski)

using Castle.DynamicProxy;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;

namespace Tests.Component.CastleTests
{
    [TestClass]
    public class GenericTest
    {
        [TestMethod]
        public void TestGeneric()
        {
            IMyPoco mypoco = ContrivedCustomIoc.Create<IMyPoco>();
            mypoco.DoWorkNoLogging();
            mypoco.DoWork();
            //Assert.IsTrue(typeof(MyPoco) == mypoco.GetType());
        }
    }

    public class ContrivedCustomIoc
    {
        private static Dictionary<string, string> mappings = new Dictionary<string, string>();

        static ContrivedCustomIoc()
        {
            //This comes from XML file
            mappings.Add("Tests.Component.CastleTests.IMyPoco", "Tests.Component.CastleTests.MyPoco");
        }

        public static T Create<T>() where T : class
        {
            string contractType = typeof(T).FullName;
            Type thisTypeInterface = Type.GetType(contractType);
            Type thisTypeConcrete = Type.GetType(mappings[contractType]);

            //Things work up until this point just fine
            //return (T)Activator.CreateInstance(thisTypeConcrete);


            var generator = new Castle.DynamicProxy.ProxyGenerator();
            //ERROR.  Class to proxy must be a class.
            //This is because T is an interface
            //Is it possible to use Castle with this custom IoC?  I want to avoid replacing the entire IoC 
            //I'd like to simply get an aspect oriented programming pattern in place
            //return generator.CreateClassProxy<T>(new MyLoggingInterceptor());

            object result = generator.CreateClassProxy(thisTypeConcrete, ProxyGenerationOptions.Default,
                new IInterceptor[1] { new MyLoggingInterceptor() });

            return (T) result;
        }
    }

    public interface IMyPoco
    {
        void DoWorkNoLogging();
        void DoWork();
    }

    public class MyPoco : IMyPoco
    {
        public void DoWorkNoLogging()
        {
            Console.Write(("Work bein done without logging"));
        }

        public virtual void DoWork()
        {
            Console.WriteLine("Work bein done!");
        }
    }

    public class MyLoggingInterceptor : IInterceptor
    {
        public void Intercept(IInvocation invocation)
        {
            try
            {
                Console.WriteLine("Interceptor starting");
                invocation.Proceed();
                Console.WriteLine("Interceptor ending");
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
            finally
            {
                Console.WriteLine("Exiting from interceptor");
            }
        }
    }
}

Solution

  • NOTE: This is summary of the comments which led to successful interceptor invocation.

    1. Use the overload of the caste proxy generator which accepts runtime type.
    2. In order to execute the interceptor you need a virtual method in the class implementation to be intercepted.