我试图了解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();
而不是ninject方式:
Bind<IPolicySearchPresenter>().To<FlexPolicySearchPresenter>().Intercept().With<IExceptionInterceptor>();
我是否需要更改我在Ninject中进行绑定的方式以获得正确的类型?
答案 0 :(得分:1)
编辑:向Foo添加了属性注入。
我为你找到了一个有效的解决方案,但说实话,我并不是百分之百。无论如何,这有效:
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
似乎.Bind()。To()和 .Bind()。ToSelf()。拦截......没有相同的结果。我不知道为什么(还) - 但也许我会调查它。
构造函数参数更新: Ninject本身只支持&#34;基于继承的类代理&#34; - 类需要默认/空ctor和&#34;接口代理而没有目标&#34; - 这是你不想要的。
因此,您可以接受使用属性注入&#34;只需这一次&#34 ;? 否则你需要创建自己的拦截ninject-magic并使用&#34;类代理与目标&#34; (见http://docs.castleproject.org/Tools.Kinds-of-proxy-objects.ashx) 备注:即使&#34;类代理与目标&#34;支持你需要知道它们之前的构造函数参数(所以没有简单的DI支持)。 (在动态代理选择/创建代理的构造函数之后,我没有找到用于解析构造函数参数的钩子。)