我试图了解 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 中进行绑定的方式才能获得正确的类型?
编辑:向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 支持)。(在动态代理为代理选择/创建构造函数后,我没有找到用于解析构造函数参数的钩子。