听起来好像您指的是普通的动态拦截器,这就是 Ninject Interception 扩展默认的工作方式。
下面是一个条件拦截的例子:
class CustomInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
if (invocation.Request.Method.Name == "MethodToIntercept")
Console.WriteLine("Intercepted!");
invocation.Proceed();
}
}
您可以将其直接绑定到单个类,如下所示:
public class MyModule : NinjectModule
{
public override void Load()
{
Bind<IFoo>().To<MyFoo>().Intercept().With<CustomInterceptor>();
}
}
如果您想动态拦截单个类,这几乎就是您所要做的。
内核扩展看起来很有希望,因为它们允许您将条件直接写入声明中:
kernel.Intercept(ctx => ctx.Request.Service == typeof(IFoo))
.With<CustomInterceptor>();
但是,如果您尝试根据正在执行的方法做出决定,这并不是特别有用,因为这只会让您访问绑定上下文,而不是调用。主要是,存在此扩展,以便您可以选择在运行时拦截哪些类或服务(而不是方法)。
最好坚持绑定语法,并将运行或不运行逻辑直接写入拦截器,如第一个示例所示。
需要注意的重要一点是,动态拦截器实际上将针对它绑定到的任何类上的每个(公共/虚拟)方法运行,这可能非常低效。不幸的是,Ninject Interception 扩展必须采用最低公分母方法,因为它旨在支持多个代理库。如果直接使用 Castle,可以使用代理生成钩子和拦截器选择器进行细粒度控制,这其实是推荐的做法。据我从 Ninject-DP2 源代码中可以看出,Ninject 扩展不支持此功能。
就个人而言,正是由于这个原因,我在 Ninject Interception 扩展方面从未取得过很大成功,并且倾向于坚持直接使用 Castle DP2。但是,如果您是在小范围内执行此操作并且不是在编写对性能敏感的应用程序,那么您应该很好地编写动态拦截器。