我在拦截教程中注意到,您可以针对方法并拦截它。即。
Kernel.Bind<Foo>().ToSelf();
Kernel.InterceptReplace<Foo>(foo => foo.ThrowsAnError(), invocation => {} );
文档/教程在您试图拦截的方法具有参数的情况下,即可涵盖该执行的操作。
Kernel.Bind<Foo>().ToSelf();
Kernel.InterceptReplace<Foo>(foo => foo.ThrowsAnError(**param goes here**), invocation => {} );
在绑定时,我无法访问参数,所以我想知道我是否以错误的方式操作?
编辑
工作示例
我认为您正在误解会发生什么。您的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时提供的参数将传递到装饰的实例。
随着拦截,这都是间接的(较慢),但概念是相同的。我必须承认,我不熟悉NInike拦截,但是invocation
对象上可能有Proceed
方法。换句话说,您应该做这样的事情:
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);
}
} );
update
我假设InterceptReplace<T>
方法的第一个参数不是委托,而是表达树,例如Expression<Action<T>>
。实际上,该方法未调用,但是可以分析以找出要拦截的方法。换句话说,由于该方法从未被调用,因此您可以提供任何参数。诀窍是让C#编译器知道要使用哪种方法过载(如果有)。是否提供垃圾都没关系。当两个参数都是参考类型时,这可能会起作用:
Kernel.InterceptReplace<Foo>(foo => foo.ThrowsAnError(null, null),