我在截取教程中已经注意到你可以定位一个方法并拦截它。即。
Kernel.Bind<Foo>().ToSelf();
Kernel.InterceptReplace<Foo>(foo => foo.ThrowsAnError(), invocation => {} );
文档/教程未涵盖在您尝试拦截的方法具有参数的情况下要执行的操作,即 ThrowsAnError 接受字符串作为参数。
Kernel.Bind<Foo>().ToSelf();
Kernel.InterceptReplace<Foo>(foo => foo.ThrowsAnError(**param goes here**), invocation => {} );
在绑定时我无法访问params,所以我想知道我是否会以错误的方式解决这个问题?
修改
答案 0 :(得分:4)
我认为你误解了会发生什么。您的Foo
对象将替换为包含拦截器的装饰器。这是一个简单的例子:
public class FooDecorator : Foo
{
private readonly Foo decorated;
public FooDecorator(Foo foo) { this.decorated = foo; }
public void ThrowsAnError(object param1, int param2)
{
// calls the decorated instance with supplied parameters
this.decorated.ThrowsAnError(param1, param2);
}
}
换句话说,调用已解析的Foo时提供的参数将被传递给修饰的实例。
然而,通过拦截,这更加间接(并且更慢),但概念是相同的。我必须承认我不熟悉Ninject拦截,但Proceed
对象上可能有一个invocation
方法。换句话说,你应该这样做:
Kernel.InterceptReplace<Foo>(foo => foo.ThrowsAnError(),
invocation =>
{
try
{
// calls the decorated instance with supplied parameters
invocation.Proceed();
}
catch (Exception ex)
{
Kernel.Get<ILogger>().Log(ex);
}
} );
<强>更新强>
我假设InterceptReplace<T>
方法的第一个参数不是委托,而是表达式树,例如Expression<Action<T>>
。事实上这个方法没有被调用,但是它被分析以找出拦截哪种方法。换句话说,由于从不调用该方法,您可以提供任何参数。诀窍是让C#编译器知道要使用哪个方法重载(如果有的话)。如果你供应垃圾并不重要。当两个参数都是引用类型时,这可能会起作用:
Kernel.InterceptReplace<Foo>(foo => foo.ThrowsAnError(null, null),