C#和AOP - AOPAlliance(面向方面​​编程)如何工作

Dan*_*tle 6 c# aop spring.net aopalliance

我在C#中有一个非常有趣的AOP体验.我有一个带有返回类型List的函数,它被截获,这一切都很好.然而,拦截器函数是验证器样式函数,可以通过调用并返回布尔值false来阻止实际函数.

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

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

// protected void Save(List<Update> updates) { ....
Save(updates);
Run Code Online (Sandbox Code Playgroud)

方法拦截器如下所示

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( ...
 }
Run Code Online (Sandbox Code Playgroud)

现在验证失败后,更新的值实际上是布尔值而不是列表,我认为这里会出现某种运行时错误但是没有,所以:

updates.GetType().Name == "Boolean"
Run Code Online (Sandbox Code Playgroud)

但:

updates is bool == false
Run Code Online (Sandbox Code Playgroud)

因此,save仍将接受其变更的更新列表,并会在您尝试使用它时稍后进行投诉.

那么在C#等类型安全的语言中,这怎么可能呢?顺便说一句,它是春天的.

编辑:这也是编译,它确实有效,我现在已经介绍了几次.

The*_*ing 6

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

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

以下是正确的,因为它正在检查实际的运行时类型,在案例中可以解析为布尔值.

updates.GetType().Name == "Boolean"
Run Code Online (Sandbox Code Playgroud)

但是下面的失败是因为它将变量的静态类型与布尔值进行比较,而不是.

updates is bool == false
Run Code Online (Sandbox Code Playgroud)

我建议您不要在Invoke中更改类型.

  • 我稍微重写了以澄清方法签名保持不变,它只是返回不同类型的代理实现.我在VS中重现了这一点,在调试器中类型显示为`System.Collections.Generic.List <string> {bool}`. (2认同)