我目前正在尝试实施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.2个滴答我必须混合INotifyAuditedChange
的逻辑,并且会引发一个事件。这不会那么糟糕,但作为我的要求的一部分,我正在寻找被修改的大量对象。
不幸的是,我使用typebuilder的计划失败了(使用Reflection.Emit编写代码太难了,显然CompileToMethod不能用于实例方法),是否有一些技巧我缺少提高DynamicProxy2的性能?