1

我目前正在尝试实现一个 AOP 系统,以向对象的修饰属性添加自动审计(由 的扩展版本完成INotifyPropertyChanged)。自动审核包含 propertyName 它的旧值和新值。

我目前正在使用 Castle 的 DynamicProxy2,因为有关于如何使用该工具的优秀教程(即这个:: http://kozmic.pl/archive/2009/04/27/castle-dynamic-proxy-tutorial.aspx ) . 我为每个为该类型装饰的属性生成一个委托。表达式树生成如下内容:: (注意我认为这比粘贴我的表达式树代码更容易,因为我的代码依赖于类型安全的反射库和许多静态变量)

.Lambda #Lambda1<System.Action`1[Castle.DynamicProxy.IInvocation]>(Castle.DynamicProxy.IInvocation $invocation) {
    .Block(
        DutchTest.MixinTest $target,
        System.Object $argument,
        System.DateTime $newValue,
        System.DateTime $oldValue) {
        $target = (DutchTest.MixinTest).Call $invocation.get_InvocationTarget();
        $newValue = .Unbox($argument = .Call $invocation.GetArgumentValue(.Default(System.Int32)));
        .If (
            .Call (.Call System.Collections.Generic.EqualityComparer`1[System.DateTime].get_Default()).Equals(
                $oldValue = .Call $target.get_Created(),
                $newValue)
        ) {
            .Default(System.Void)
        } .Else {
            .Block() {
                .Call $invocation.Proceed();
                .Call ($target .As Dutch.Auditing.INotifyAuditedChange).OnPropertyChanged(.New Dutch.Auditing.AuditEventArgs(
                        "Created",
                        (System.Object)$oldValue,
                        $argument))
            }
        }
    }
}

然后我有一个自定义选择器,它选择了DelegatedInterceptor(一个实现 IInterceptor 的类,它的 Intercept 方法只是为了调用委托。我还有一个自定义钩子,它只选择我计划委托的属性(所以我避免了代理 get 方法)。

不幸的是,即使采取了所有这些预防措施,我仍然看到每个属性集的性能都会受到重大影响(手动执行该逻辑大约需要 0.4 个滴答声,如果我使用动态代理执行该逻辑大约需要 2.2 个滴答声,如果我必须这样做则需要 2.8 个滴答声混合逻辑,INotifyAuditedChange并引发事件)。这不会那么糟糕,但作为我的要求的一部分,我正在查看大量正在修改的对象。

不幸的是,我使用 typebuilder 的计划失败了(用 Reflection.Emit 编写代码太难了,显然 CompileToMethod 不能用于实例方法),我是否缺少一些技巧来提高 DynamicProxy2 的性能?

4

0 回答 0