在运行时替换Property Setter方法

我有许多对象都共享一个公共基类,我希望拦截所有设置属性值的调用,并记录这些是否基于每个实例设置。

我可以在运行时用Reflection替换属性的Set方法吗?

一种方法是使属性成为虚拟,并在运行时通过reflection-emit创建一个子类,覆盖属性,添加代码。 但是,这是先进的,并且要求您始终确保创建子类(因此代码中没有“新”)。

然而; 我想知道简单地实现INotifyPropertyChanged并处理事件更简单。 另一种选择是首先将处理构建到常规类中。 有一些方法可以减少重复次数,特别是如果你有一个可以添加的公共基类

protected void SetField(ref T field, T value) { if(!EqualityComparer.Default.Equals(field,value)) { field = value; // extra code here } } 

 private int foo; public int Foo { get { return foo; } set { SetField(ref foo, value); } } 

如果您的基类派生自ContextBoundObject您可以在不同的Context(在同一AppDomain )和拦截方法调用(属性是什么)中创建对象,并将您自己的消息接收器插入到远程接收器链中。

这是一个例子

http://www.codeproject.com/KB/cs/aspectintercept.aspx

您无法在运行时直接替换它。 如果该属性是虚拟的,您可以使用像Castle的http://www.castleproject.org/dynamicproxy/index.html这样的DynamicProxy来为您创建扩展您的类型的代理类型,并且它的工厂可用于获取类有办法拦截它的方法。

或者,您可以使用ContextBoundObject路由或Enterprise Libaries Policy Injectionhttp://msdn.microsoft.com/en-us/library/cc511729.aspx

警告ContextBoundObject比Castle的动态代理慢得多,但您不必将方法声明为虚拟。 Policy Injection只允许您在调用建议之前或之后插入,因此如果您因任何原因反对调用,则无法停止调用。

如果您可以将此作为后编译步骤处理,则可以使用PostSharp或Mono.Cecil。

我个人正在使用我自己的动态代理,它允许用Delegates替换方法,但它还没有准备好用于石灰灯。