Castle Windsor Cannot Intercept Component Registered For A Class Instance

对着背影说爱祢 提交于 2020-01-15 11:05:51

问题


I have problem intercepting a component registered to a class intance.

//this does not get intercepted
container.Register(Component.For<IService>().Instance(instanceService)
                                .Interceptors<Interceptor>());

Interceptor works if I register the component without using the class instance

//this get intercepted
container.Register(Component.For<IService>().ImplementedBy<SampleService>()
                         .Interceptors<Interceptor>());

Is this a bug or by design?

Thanks

This is unit test code.

    [Test]
    public void Test_Windsor_Interceptor_With_Instance_Component_Registration()
    {
        IService instanceService = new SampleService();

        var container = new WindsorContainer();
        container.Register(Component.For<Interceptor>());

        //this get intercepted
        container.Register(Component.For<IService>().ImplementedBy<SampleService>()
                            .Interceptors<Interceptor>());

        ////this does not get intercepted
        //container.Register(Component.For<IService>().Instance(instanceService)
        //                    .Interceptors<Interceptor>());

        var proxiedService = container.Resolve<IService>();

        proxiedService.DoSomething();


    }

    public class Interceptor : Castle.DynamicProxy.IInterceptor
    {
        public void Intercept(Castle.DynamicProxy.IInvocation invocation)
        {
            throw new System.NotImplementedException("Interceptor succesfully called but not implemented");
        }
    }

    public interface IService
    {
        void DoSomething();
    }

    public class SampleService : IService
    {
        public void DoSomething()
        {
            string dummy = string.Empty;
        }
    }

回答1:


It's by design. You can't expect Windsor to wire up an interceptor if you're manually instantiating the object.




回答2:


You actually can intercept a registered instance by using an interceptor selector, but it would be nice if it worked the way "kite" outlined above. Here's how. This example is specific to my implementation, but there is enough detail to figure it out for your own usage.

StubISecurityService instance= new StubISecurityService();
Container.Register(Component.For<ISecurityService>().Instance(instance));

//Apply the interceptors.
Container.Kernel.ProxyFactory.AddInterceptorSelector(new InterceptorSelector<SecurityInterceptor>(model => model.Implementation == typeof(ExampleSecureService)));

IExampleSecureService exampleSecureService = Container.Resolve<IExampleSecureService>();

/// <summary>
/// A generic implementation of <see cref="IModelInterceptorsSelector"/> used to apply a single interceptor on matching types.
/// </summary>
/// <typeparam name="TInterceptor">The type of the interceptor.</typeparam>
public class InterceptorSelector<TInterceptor> : IModelInterceptorsSelector {
    private readonly Func<ComponentModel, bool> _selector;

    /// <summary>
    /// Initializes a new instance of the <see cref="InterceptorSelector{TInterceptor}"/> class.
    /// </summary>
    /// <param name="selector">The function used to find matching types.</param>
    public InterceptorSelector(Func<ComponentModel, bool> selector) {
        _selector = selector;
    }

    public virtual bool HasInterceptors(ComponentModel model) {
        bool isNotItself = typeof(TInterceptor) != model.Implementation;
        bool isMatch = _selector.Invoke(model);
        return isNotItself && isMatch;
    }

    public virtual InterceptorReference[] SelectInterceptors(ComponentModel model, InterceptorReference[] interceptors) {
        return new[] {InterceptorReference.ForType<TInterceptor>()};
    }
}


来源:https://stackoverflow.com/questions/12162769/castle-windsor-cannot-intercept-component-registered-for-a-class-instance

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!