组件已经注册后,Castle Windsor将拦截器与选择器一起使用

Ner*_*roS 7 .net c# aop castle-windsor interceptor

我有一个抽象的基类,它包含几个方法,其中一个我需要随时拦截.基类可以由用户定义的类继承,并在应用程序启动时向容器注册.如果用户尚未注册,则容器安装程序将自行注册一个.

这是问题 - 用户不必担心添加拦截器.容器应该自己添加它,无论注册组件的人和位置.

这就是我现在正在做的事情:

if(!container.Kernel.HasComponent(typeof(MyBaseComponent)))
    container.Register(Component.For<MyComponent>()
        .Interceptors(InterceptorReference
        .ForType<MyComponentMethodInterceptor>())
        .SelectedWith(new MyComponentMethodSelector()).AtIndex(1));
Run Code Online (Sandbox Code Playgroud)

MyComponentMethodSelector是一个简单的IInterceptorSelector,它检查methodname是否等于我需要拦截的那个(在这种情况下MyComponentMethodInterceptor会添加一个).

如您所见,它将检查组件是否已首先注册.

问题是 - 如果已经注册,我是否有办法添加拦截器?想到的最明显的选择是使用a IContributeComponentModelConstruction,但是在那时我将无法选择拦截器添加到的方法.还是有吗?

编辑:

我本来应该更具体一点.我只需要为特定方法添加拦截器.因此我为什么使用MyComponentMethodSelector.我知道IContributeComponentModel,我开始用它直到我意识到我无法添加方法选择器.

sam*_*amy 8

您可以使用ComponentModel构造参与者轻松地将组件添加到组件,该构建参与者通过实现在构建服务的组件模型时调用IContributeComponentModelConstruction.

假设你想要为任何实现添加一个拦截器IEventuallyRegistered,如果用户没有注册你想要使用的自定义组件DefaultRegistration:

public interface IEventuallyRegistered { void test(); }
public class DefaultRegistration : IEventuallyRegistered { public void test() { } }
public class EventuallyRegisteredInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation) { invocation.Proceed(); }
}

internal class Program
{
    private static void Main(string[] args)
    {
        var container = new Castle.Windsor.WindsorContainer();
        container.Register(Component.For<EventuallyRegisteredInterceptor>());
        container.Register(Component.For<IEventuallyRegistered>().ImplementedBy<DefaultRegistration>());
        // I'm not doing the optional registration, I just want to 
        // demonstrate upgrading a additional configuration

        var t = container.Resolve<IEventuallyRegistered>();
        t.test();
    }
}
Run Code Online (Sandbox Code Playgroud)

通过实现IContributeComponentModelConstruction界面,您可以在创建组件模型时更改其配置:

public class RequireInterception : IContributeComponentModelConstruction
{
    public void ProcessModel(IKernel kernel, ComponentModel model)
    {
        if (model.Services.Contains(typeof(IEventuallyRegistered)))
        {
            model.Interceptors.Add(new InterceptorReference(typeof(EventuallyRegisteredInterceptor)));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后注册组件之前将组件添加到容器中:

container.Kernel.ComponentModelBuilder.AddContributor(new RequireInterception());
container.Register(Component.For<IEventuallyRegistered>().ImplementedBy<DefaultRegistration>());
Run Code Online (Sandbox Code Playgroud)

尽管可以通过ComponentRegistered具有工具的内核事件来实现,但不建议这样做 ; 因为它包含在原始答案中,所以我将其包括在内但我正在推动它.您将从创建工具开始

public class InterceptionFacility : AbstractFacility
{
    protected override void Init()
    {
        Kernel.ComponentRegistered += new Castle.MicroKernel.ComponentDataDelegate(Kernel_ComponentRegistration);
    }

    void Kernel_ComponentRegistration(string key, Castle.MicroKernel.IHandler handler)
    {
        if (typeof(IEventuallyRegistered).IsAssignableFrom(handler.ComponentModel.Implementation))
        {
            handler.ComponentModel.Interceptors.Add(new InterceptorReference(typeof(EventuallyRegisteredInterceptor)));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在注册组件之前将工具添加到容器中,否则您的工具将在注册组件时错过该事件:

container.AddFacility<InterceptionFacility>();
container.Register(Component.For<IEventuallyRegistered>().ImplementedBy<DefaultRegistration>());
Run Code Online (Sandbox Code Playgroud)

  • `IProxyGenerationHook` 就是您所追求的。http://kozmic.net/2009/01/17/castle-dynamic-proxy-tutorial-part-iii-selecting-which-methods-to/ 您可以通过 `var options = model.ObtainProxyOptions(); 设置它 选项.Hook = 钩子;` (2认同)