6

我刚刚在 C# 中使用 AOP 获得了非常有趣的体验。我有一个返回类型 List 的函数,它被拦截了,这一切都很好。然而,拦截器函数是一个验证器风格的函数,可以通过调用并返回布尔值 false 来阻止真正的函数。

所以代码看起来有点像这样:

List<Update> updates = Manager.ValidateAndCreate();

// protected void Save(List<Update> updates) { ....
Save(updates);

方法拦截器如下所示

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# 这样的类型安全语言中怎么可能呢?顺便说一句,这是spring-aop。

编辑:这也确实编译并且它确实有效,我已经通过它几次了。

4

1 回答 1

6

我相信这是可能的,因为 Spring.Net 在运行时发出代理类,跳过编译时类型检查。

它本质上实现了一个包装原始类并动态生成新方法实现的装饰器模式。在动态生成的代理方法中,可以在编写 IL 时更改返回类型,而 .NET 允许这样做,因为它不会在运行时检查类型。当然,在编译时它仍然是完全有效的。这导致了上面相当奇怪的场景,即您的静态类型实际上与运行时类型不同。

以下是正确的,因为它正在检查实际的运行时类型,在某些情况下可以解析为布尔值。

updates.GetType().Name == "Boolean"

但是以下失败了,因为它将变量的静态类型与布尔值进行比较,但事实并非如此。

updates is bool == false

我建议您不要更改 Invoke 中的类型。

于 2011-08-27T01:30:02.440 回答