为什么 Ninject 绑定与拦截返回接口代理

本文关键字:返回 接口 代理 Ninject 绑定 为什么 | 更新日期: 2023-09-27 18:35:14

我试图了解 Ninject.Extensions.Interception 3.0.0.8 如何为我的类构建动态代理。我发现当我使用继承自InterceptAttribute的属性装饰我的具体类时,或者当我使用Intercept()方法在绑定时直接拦截时,Ninject 返回装饰类的动态代理而不是普通类型。

我有一个IPolicySearchPresenter接口,我将其绑定到FlexPolicySearchPresenter添加异常记录器拦截器的具体类型:

Bind<IExceptionInterceptor>().To<ExceptionInterceptor>();
Bind<IPolicySearchPresenter>().To<FlexPolicySearchPresenter>().Intercept().With<IExceptionInterceptor>();

问题是,当我检查该绑定的返回类型时:

var proxy = Kernel.Get<IPolicySearchPresenter>();

我得到一个Castle.Proxies.IPolicySearchPresenterProxy实例而不是FlexPolicySearchPresenterProxy

这给我的 FluorineFx 远程处理应用程序带来了问题。但是,如果我手动创建我的城堡代理:

ProxyGenerator generator = new ProxyGenerator();
    //My presenter type
    Type type = typeof(FlexPolicySearchPresenter);
    //My presenter interface
    var interfaceType = type.GetInterfaces().Single();
    //Get my Interceptor from container. Notice that i had to 
    //change my Interceptor to implement IInterceptor from Castle libs,
    // instead of Ninject IInterceptor
    var excepInt = Kernel.Get<ExceptionInterceptor>();
    //Manually get all my instances required by my presenter type Constructor
    //ideally passed through Constructor Injection
    var presenterSearchService = Kernel.Get<IPolicySearchService>();
    var userAuthService = Kernel.Get<IUserAuthorizationService>();
    //Create proxy, passing interceptor(s) and constructor arguments
    var proxy = generator.CreateClassProxy(type, new object[] { presenterSearchService, userAuthService },
            new IInterceptor[]
        {
            excepInt
        });
    //Ninject.Extensions.Interception.DynamicProxyModule
    // I'm using directive ToConstant(..), and not To(..)
    //Bind my interface to the new proxy
    Bind(interfaceType).ToConstant(proxy).InThreadScope();
var proxy = Kernel.Get<IPolicySearchPresenter>();
返回

的类型以Castle.Proxies.FlexPolicySearchPresenterProxy形式返回,与我的远程实现完美配合。

问题是,我怎样才能让Ninject.Interception返回FlexPolicySearchPresenterProxy实例而不是IPolicySearchPresenterProxy。请注意,通过执行手动 Castle 方式,我以不同的方式绑定:

        Bind(interfaceType).ToConstant(proxy).InThreadScope();

而不是注入方式:

Bind<IPolicySearchPresenter>().To<FlexPolicySearchPresenter>().Intercept().With<IExceptionInterceptor>();

我是否需要更改在 Ninject 中进行绑定的方式才能获得正确的类型?

为什么 Ninject 绑定与拦截返回接口代理

编辑:向Foo添加了属性注入。

我有一个

适合您的工作解决方案,但老实说,我对此并不 100% 满意。无论如何,这有效:

class Program
{
    static void Main(string[] args)
    {
        var kernel = new StandardKernel();
        kernel.Bind<IFoo>().ToMethod(ctx => ctx.Kernel.Get<Foo>());
        kernel.Bind<Foo>().ToSelf().Intercept().With<SomeInterceptor>();
        var foo = kernel.Get<IFoo>();
        foo.DoSomething();
        Console.WriteLine(foo.GetType());
        Console.Read();
    }
}
public interface IFoo
{
    void DoSomething();
}
public class Foo : IFoo
{
    [Inject]
    public Bar Dependency { get; set; }
    public virtual void DoSomething()
    {
        Console.WriteLine("doing something with {0}", this.Dependency);
    }
}
public class SomeInterceptor : IInterceptor
{
    public SomeInterceptor()
    {
        Console.WriteLine("interceptor created");
    }
    public void Intercept(IInvocation invocation)
    {
        Console.WriteLine("before");
        invocation.Proceed();
        Console.WriteLine("after");
    }
}
public class Bar
{
    public override string ToString()
    {
        return "Bar (injected dependency)";
    }
}

生成的输出为:

interceptor created
before
doing something with Bar (injected dependency)
after

类型是:

Castle.Proxies.FooProxy

似乎.绑定()。To() 。绑定()。到自我()。拦截。。。没有相同的结果。我不知道为什么(还) - 但也许我要调查它。

构造函数参数的更新:Ninject本身仅支持"基于继承的类代理" - 其中类需要默认/空的ctor和"没有目标的接口代理" - 这是您不想要的。

因此,您是否可以接受"仅此一次"使用属性注入?否则,您将需要创建自己的拦截ninject-magic并使用"带目标的类代理"(见 http://docs.castleproject.org/Tools.Kinds-of-proxy-objects.ashx)备注:即使"带目标的类代理"支持构造函数参数,您也需要事先知道它们是哪个(所以没有简单的 DI 支持)。(在动态代理为代理选择/创建构造函数后,我没有找到用于解析构造函数参数的钩子。

相关文章: