[英]Why is Ninject Bind with Interception returning an interface proxy?
I'm trying to understand how Ninject.Extensions.Interception
3.0.0.8 is building dynamic proxies for my classes. 我试图了解Ninject.Extensions.Interception
3.0.0.8如何为我的课程构建动态代理。 I've found that when I decorate my concrete classes with an attribute that inherits from InterceptAttribute
or when I directly Intercept at binding time with Intercept()
method then Ninject returns a Dynamic Proxy of the decorated class instead of the normal type. 我发现,当我用继承自InterceptAttribute
的属性来装饰具体类时,或者当我在绑定时使用Intercept()
方法直接进行拦截时,Ninject会返回装饰类的动态代理,而不是普通类型。
I have a IPolicySearchPresenter
interface which I'm binding to FlexPolicySearchPresenter
concrete type adding an Exception logger interceptor: 我有一个IPolicySearchPresenter
接口,该接口绑定到FlexPolicySearchPresenter
具体类型,并添加一个Exception logger拦截器:
Bind<IExceptionInterceptor>().To<ExceptionInterceptor>();
Bind<IPolicySearchPresenter>().To<FlexPolicySearchPresenter>().Intercept().With<IExceptionInterceptor>();
The problem is that when I inspect the returning type for that binding: 问题是当我检查该绑定的返回类型时:
var proxy = Kernel.Get<IPolicySearchPresenter>();
I get an instance of Castle.Proxies.IPolicySearchPresenterProxy
instead of FlexPolicySearchPresenterProxy
我得到了Castle.Proxies.IPolicySearchPresenterProxy
的实例,而不是FlexPolicySearchPresenterProxy
的实例
This is giving me problems with my FluorineFx remoting app. 这给我的FluorineFx远程处理应用程序带来了问题。 However, if I create my Castle Proxy manually: 但是,如果我手动创建我的城堡代理:
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>();
The returning types come back as Castle.Proxies.FlexPolicySearchPresenterProxy
which work perfectly with my remoting implementation. 返回的类型以Castle.Proxies.FlexPolicySearchPresenterProxy
形式返回,与我的远程实现完美配合。
The question is, how can I get Ninject.Interception return me instances of FlexPolicySearchPresenterProxy
instead of IPolicySearchPresenterProxy
. 问题是,如何获得Ninject.Interception可以返回FlexPolicySearchPresenterProxy
实例,而不是IPolicySearchPresenterProxy
实例。 Notice that by doing the manual Castle way I am binding in a different way: 请注意,通过执行手动Castle方法,我以另一种方式进行绑定:
Bind(interfaceType).ToConstant(proxy).InThreadScope();
Instead of the ninject way: 代替ninject方式:
Bind<IPolicySearchPresenter>().To<FlexPolicySearchPresenter>().Intercept().With<IExceptionInterceptor>();
Do I need to change the way I'm doing the Binding in Ninject to get the right type? 我是否需要更改在Ninject中进行绑定的方式以获得正确的类型?
Edit: added property injection to Foo. 编辑:将属性注入添加到Foo。
I've got a working solution for you, but to be honest, i'm not 100% happy about it. 我为您提供了一个可行的解决方案,但是老实说,我对此不是100%满意。 Anyway, this works: 无论如何,这可行:
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)";
}
}
The resulting output is: 结果输出为:
interceptor created
before
doing something with Bar (injected dependency)
after
And the type is: 类型是:
Castle.Proxies.FooProxy
It seems that .Bind().To() and .Bind().ToSelf().Intercept... do not have the same result. 似乎.Bind()。To() 和 .Bind()。ToSelf()。Intercept ...没有相同的结果。 I don't know why (yet) - but maybe i'm going to investigate it. 我不知道为什么(但)-但也许我要对此进行调查。
Update on constructor arguments: Ninject by itself only supports "inheritance based class proxy" - where the class needs a default / empty ctor and "interface proxy without target" - which is what you don't want. 构造函数参数上的更新: Ninject本身仅支持“基于继承的类代理”-其中类需要默认/空ctor和“没有目标的接口代理”-这是您不想要的。
Therefore, would it be acceptable for you to use property injection "just this once"? 因此,使用属性注入“仅此一次”是否可以接受? Otherwise you will need to create your own interception ninject-magic and use "class proxy with target" (see http://docs.castleproject.org/Tools.Kinds-of-proxy-objects.ashx ) Remark : Even though "class proxy with target" supports constructor arguments you need to know which they are beforehand (so no easy DI support). 否则,您将需要创建自己的拦截ninject-magic并使用“带有目标的类代理”(请参阅http://docs.castleproject.org/Tools.Kinds-of-proxy-objects.ashx ) 备注 :即使“ class”具有目标的代理”支持构造函数参数,您需要事先知道它们是什么(因此不容易获得DI支持)。 (I did not find a hook for resolving constructor arguments after dynamic proxy chooses/creates the constructor for the proxy.) (在动态代理选择/创建代理的构造函数之后,我没有找到解决构造函数参数的钩子。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.