根据您的要求,我将详细介绍我们如何实现“1 个代理:1 个拦截器”实例关系。
我们采用了一种简单的方法,它没有提供官方 ninject 拦截扩展提供的灵活性。我们直接依赖castle.core 动态代理和castle 的IInvocation
接口。
(请注意,下面的代码是针对没有目标的代理的,但是有目标的代理非常相似——唯一的变化是您需要知道目标类的类型并用于IResolutionRoot.Get<TargetClassType>()
实例化它)。
基本上我们创建了一个绑定,如:
IBindingRoot.Bind<IFoo>()
.ToProvider<InterfaceProxyWithoutTargetProvider<IFoo>>();
现在我们当然需要知道代理应该使用哪些拦截器。我们再次使用了一个简单但不太好的设计:
public interface IInterceptorBindingDefinition<TTarget>
{
Type InterceptorType { get; }
}
public class InterceptorBindingDefinition<TTarget, TInterceptor> : IInterceptorBindingDefinition<TTarget>
where TInterceptor : IInterceptor
{
Type InterceptorType { get { return typeof(TInterceptor); } }
}
IBindingRoot
.Bind<IInterceptorBindingDefinition<IFoo>>()
.To<InterceptorBindingDefinition<TTarget, LoggingInterceptor>();
IBindingRoot
.Bind<IInterceptorBindingDefinition<IFoo>>()
.To<InterceptorBindingDefinition<TTarget, SomeOtherInterceptor>();
这意味着IFoo
将获得两个拦截器:LoggingInterceptor
和SomeOtherInterceptor
.
以及提供者的实现:
public class InterfaceProxyWithoutTargetProvider<TInterface> : IProvider<TInterface>
where TInterface : class
{
private readonly IProxyGenerator proxyGenerator;
private readonly IInterceptorFactory interceptorFactory;
public InterfaceProxyWithoutTargetProvider(IProxyGenerator proxyGenerator, IInterceptorFactory interceptorFactory)
{
this.proxyGenerator = proxyGenerator;
this.interceptorFactory = interceptorFactory;
}
public Type Type
{
get { return typeof(TInterface); }
}
public object Create(IContext context)
{
var interceptorTypes = context.Kernel.Get<IEnumerable<IInterceptorBindingDefinition<TInterface>>();
IList<IInterceptor> interceptors = interceptorTypes
.Select(x => x.InterceptorType)
.Select(x => context.ContextPreservingGet(x))
.ToList();
return this.proxyGenerator.CreateInterfaceProxyWithoutTarget<TInterface>(interceptors);
}
}
当然,现在我们稍微完善了这个东西,所以我们有一个流畅的语法来配置代理和拦截器的绑定——这很容易。
然而 ninject.extensions.interception 的方法和它IAdviceRegistry
当然IAdvice
更好(但也需要更深入地了解 ninject 的工作原理)。