我在C#中获得了非常有趣的AOP体验。我有一个带有返回类型List的函数,它被截获,这一切都很好。然而,拦截器函数是一个验证器样式函数,可以通过调用并返回布尔值false来阻止实际函数。
所以代码看起来有点像这样:
List<Update> updates = Manager.ValidateAndCreate();
// protected void Save(List<Update> updates) { ....
Save(updates);
Method Interceptor如下所示
public class ExceptionAdvice : AopAlliance.Intercept.IMethodInterceptor {
public object Invoke(AopAlliance.Intercept.IMethodInvocation invocation) {
if (isValid(invocation)) {
return invocation.Proceed();
} else {
return false;
}
}
private bool isValid( ...
}
现在验证失败后,更新的值实际上是布尔值而不是列表,我认为这里会出现某种运行时错误但是没有,所以:
updates.GetType().Name == "Boolean"
但是:
updates is bool == false
因此,save仍会接受其变更的更新列表,并会在您尝试使用它时稍后进行投诉。
那么在C#这样的类型安全语言中,这怎么可能呢?顺便说一句,它是春天的。
编辑:这也是编译它确实有效我现在已经介绍了几次。
答案 0 :(得分:6)
我相信这是可能的,因为Spring.Net在运行时发出代理类,跳过编译时类型检查。
它实质上实现了一个包装原始类并动态生成新方法实现的装饰器模式。在动态生成的代理方法中,返回类型在写入IL时可以更改,而.NET允许它,因为它不会在运行时检查类型。在编译时,它当然仍然完全有效。这导致了上面相当奇怪的情况,即静态类型实际上与运行时类型不同。
以下是正确的,因为它正在检查实际的运行时类型,在案例中可以解析为布尔值。
updates.GetType().Name == "Boolean"
但是下面的失败是因为它将变量的静态类型与布尔值进行比较,而不是布尔值。
updates is bool == false
我建议您不要在Invoke中更改类型。