拦截由 Castle Windsor 3.0 的 Startable 设施调用的方法

发布于 2024-12-25 02:34:08 字数 1847 浏览 2 评论 0原文

我正在使用温莎城堡3.0。

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

为了使我的组件可启动,我使用了 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 方法。异常被抛出并被我的自定义拦截器拦截。

那么,正如本文标题所问的那样,有没有办法用 Windsor 拦截 Startable 设施调用的方法?

问候

路易斯·皮埃尔·博蒙特

I'm using Castle Windsor 3.0.

I have a component that should be started automatically after the registration phase.
I would also like to intercept exceptions coming from it's Start/Stop methods and log their details.

To make my component startable, I used the Startable facility that comes with Windsor:

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

I created a custom interceptor like this:

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);
        }
    }
}

and I registered the component like this:

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

To make a test, I coded a dirty

throw new Exception(); 

in the implementation of the Start method of the component. At registration phase, when Windsor automatically calls the Start method on the component, the exception is thrown, but never intercepted by my custom interceptor.

I made another test, this time without using the Startable facility but rather calling the Start method manually. The exception got thrown and was intercepted by my custom interceptor.

So, as the title of this post asks, is there a way to intercept methods called by the Startable facility with Windsor?

Regards

Louis-Pierre Beaumont

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

木落 2025-01-01 02:34:08

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

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

此处专门发布了该问题。

不管怎样,我很快就发现使用代理对象进行 AOP 有它的局限性。这就是我转向 SheepAspect(一个 IL Weaving AOP 框架)的原因。

我将 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;
    }
}

I'm going to partially answer my own question:

I did not find any way to intercept the Start method on a component when using the Startable facility. It looks like the facility is not using the proxy created for the object to perform the call, but the object itself.

A dedicated post presents the problem here.

Anyway, I quicly figured out that doing AOP with Proxy objects has it's limits. That's why I moved to SheepAspect, an IL Weaving AOP Framework.

I mixed SheepAspect with Castle Windsor, and now, when my component's Start method is called by the Castle Startable facility, all my aspects are also called!

Here is how i wrote my ExceptionAspect with SheepAspect:

[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;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文