拦截方法由Startable工厂调用Castle Windsor 3.0

时间:2012-01-04 23:20:57

标签: interface dependency-injection castle-windsor aop interceptor

我正在使用Castle Windsor 3.0。

我有一个应该在注册阶段后自动启动的组件。 我还想拦截来自它的Start / Stop方法的异常并记录它们的详细信息。

为了使我的组件可以启动,我使用了Windsor附带的Startable工具:

container.AddFacility<StartableFacility>(f => f.DeferredStart());

我创建了一个这样的自定义拦截器:

class ExceptionLoggerInterceptor : IInterceptor
{
    IExceptionLogger m_ExceptionLogger;

    public ExceptionLoggerInterceptor(IExceptionLogger exceptionLogger)
    {
        if (exceptionLogger == null)
            throw new ArgumentNullException("exceptionLogger");

        m_ExceptionLogger = exceptionLogger;
    }

    public void Intercept(IInvocation invocation)
    {
        try
        {
            invocation.Proceed();
        }
        catch (Exception ex)
        {
            m_ExceptionLogger.Write(ex, invocation.Method.Name, invocation.TargetType.Name);
        }
    }
}

我注册了这样的组件:

Component.For<IExceptionLogger>()
 .ImplementedBy<EnterpriseLibraryExceptionLogger>()
 .LifeStyle.Singleton,

Component.For<ExceptionLoggerInterceptor>()
 .LifeStyle.Singleton,

Component.For<IWorkflowService>()
 .ImplementedBy<WorkflowService>()
 .LifeStyle.Singleton
 .StartUsingMethod(c => c.Start)
 .StopUsingMethod(c => c.Stop)
 .Interceptors(InterceptorReference.ForType<ExceptionLoggerInterceptor>()).Anywhere

为了进行测试,我编写了一个脏的

throw new Exception(); 

在组件的Start方法的实现中。在注册阶段,当Windsor自动调用组件上的Start方法时,抛出异常,但不会被我的自定义拦截器截获。

我做了另一个测试,这次没有使用Startable工具,而是手动调用Start方法。异常被抛出并被我的自定义拦截器截获。

所以,正如这篇文章的标题所要求的那样,是否有办法拦截Startable工具与Windsor调用的方法?

此致

Louis-Pierre Beaumont

1 个答案:

答案 0 :(得分:2)

我将部分回答我自己的问题:

使用Startable工具时,我没有找到任何方法拦截组件上的Start方法。看起来设施没有使用为对象创建的代理来执行调用,而是使用对象本身。

专门的帖子提出问题here

无论如何,我非常清楚地知道用代理对象做AOP有它的限制。这就是为什么我转向使用IL编织AOP框架的SheepAspect。

我将SheepAspect与Castle Windsor混合,现在,当Castle Startable工具调用我的组件的Start方法时,我的所有方面也都被调用了!

以下是我用SheepAspect编写ExceptionAspect的方法:

[SingletonAspect]
public class ExceptionAspect
{
    IExceptionLogger m_ExceptionLogger;

    public ExceptionAspect(IExceptionLogger exceptionLogger)
    {
        if (exceptionLogger == null)
            throw new ArgumentNullException("exceptionLogger");

        m_ExceptionLogger = exceptionLogger;
    }

    [SelectTypes(typeof(WorkflowService))]
    void Targets() { }

    [Around("Execute")]
    [SelectMethods("Name:('Start') & InType:@Targets")]
    public void Execute(MethodJointPoint jp)
    {
        object result = null;

        try
        {
            result = jp.Execute();
        }
        catch (Exception ex)
        {
            m_ExceptionLogger.Write(ex, jp.Method.Name, jp.Method.ReflectedType.Name);
        }

        return result;
    }
}