Search code examples
castle-windsorcastle-dynamicproxy

Architecting applications with Castle Windsor


I am currently trying to achieve AOP using Castle. I have created a .NET solution that takes care of the business (lets name it Project 1). I am thinking of creating a separate project that would house all of my AOP related classes (aspects) (This is named Project 2). My questions are :

1) Is it possible to use an xml configuration file in Project 1 to configure which aspects to apply during runtime? (I have a fair idea on the possibility of this, but let me know if its otherwise)

2) Is it possible to not touch the Project 1 (code change/rebuilding) for adding new aspects/ removing old aspects and have all of this governed via Project 2? Rephrasing, I do not want to change/build my business solution due to future additions or deletions of aspects.


Solution

  • You can configure components with XML (https://github.com/castleproject/Windsor/blob/master/docs/registering-components.md), this wouldn't require rebuild, also it is possible for project 2 to configure AOP, you can get project 1 to call out to project 2 to register the IOC services, from this point on you can register interceptors to act as aspects and apply them to any component you wish, project 2 will need to reference project 1 or the project which contains the interfaces and implementations that you wish to register these for.

    example:

    container.Register(
       Component.For<LoggingInterceptor>().Lifestyle.Transient,
       Component.For<CacheInterceptor>().Lifestyle.Transient,
       Component.For<IOrderRepository>().ImplementedBy<OrderRepository>());
    

    You would not have to change business code, you can register interceptors orthgonally, in project 2 you would reference the business project and register any custom interceptors against that interface. You can avoid xml configuration altogether and do it in project 2, you would rebuild project 2 drop it in, and restart the app. you can register interceptor with xml too (https://github.com/castleproject/Windsor/blob/master/docs/xml-registration-reference.md)

    see section interceptor and proxy components section in https://github.com/castleproject/Windsor/blob/master/docs/registering-components.md, for xml configuratino of interceptors.

    so for example:

    Console App Project (references aop and business project)

    static void Main(string[] args)
    {
        var container = IocContainerFactory.GetContainer();
    
        ISomeBusinessService service = container.Kernel.Resolve<ISomeBusinessService>();
    
        Console.WriteLine(service.ReturnSomething());
        Console.ReadLine();
    }
    

    Business Project

    public interface ISomeBusinessService
    {
        string ReturnSomething();
    }
    
    public class SomeBusinessService : ISomeBusinessService
    {
        public string ReturnSomething()
        {
            return "some business value from service";
        }
    }
    

    AOP project (references business project)

    public static class IocContainerFactory
    {
        public static IWindsorContainer GetContainer()
        {
            var container = new WindsorContainer();
    
            container.Register(Component.For<IInterceptor>().ImplementedBy<TraceLoggingInterceptor>().LifestyleTransient());
            container.Register(Component.For<ISomeBusinessService>().ImplementedBy<SomeBusinessService>().LifestyleTransient().Interceptors<TraceLoggingInterceptor>());
    
            return container;
        }
    }
    
    public class TraceLoggingInterceptor : IInterceptor
    {
        public void Intercept(IInvocation invocation)
        {
            Console.WriteLine("{0} - {1}", invocation.TargetType, invocation.Method);
            invocation.Proceed();
        }
    }