我目前正在尝试实现一个 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 的性能?