我觉得你理解错了发生的事情。你的Foo
对象被替换成了一个包含拦截器的装饰器。这里是一个简单的例子:
public class FooDecorator : Foo
{
private readonly Foo decorated;
public FooDecorator(Foo foo) { this.decorated = foo; }
public void ThrowsAnError(object param1, int param2)
{
this.decorated.ThrowsAnError(param1, param2);
}
}
换句话说,在调用已解析的Foo时提供的参数将传递给装饰实例。
然而,使用拦截器时,这一切都有些间接(并且更慢),但概念是相同的。我必须承认,我不熟悉Ninject拦截,但invocation
对象上可能有一个Proceed
方法。换句话说,您应该这样做:
Kernel.InterceptReplace<Foo>(foo => foo.ThrowsAnError(),
invocation =>
{
try
{
invocation.Proceed();
}
catch (Exception ex)
{
Kernel.Get<ILogger>().Log(ex);
}
} );
更新
我假设InterceptReplace<T>
方法的第一个参数不是委托,而是表达式树,例如Expression<Action<T>>
。 实际上,此方法并没有被调用,只是被分析以找出要拦截的方法。换句话说,由于该方法从未被调用,您可以随意提供任何参数。关键在于让C#编译器知道使用哪个方法重载(如果有)。如果两个参数都是引用类型,那么这可能会起作用,无论您提供什么内容。
Kernel.InterceptReplace<Foo>(foo => foo.ThrowsAnError(null, null),
Kernel.InterceptReplace<Foo>(foo => foo.ThrowsAnError(),...);
需要在其中输入参数,否则它不会编译,因为ThrowsAnError需要N个参数,对于你的情况,你必须像这样绑定:Kernel.InterceptReplace<Foo>(foo => foo.ThrowsAnError(somehowSatisfyParam1, somehowSatisfyParam2), ...);
虽然我可能是错的。 - Grofitfoo.ThrowsAnError()
仍然需要指定参数。 - Mark Walsh