在运行时替换Property Setter方法

时间:2010-12-04 07:45:38

标签: c# reflection

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

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

3 个答案:

答案 0 :(得分:6)

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

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

的公共基类
protected void SetField<T>(ref T field, T value)
{
    if(!EqualityComparer<T>.Default.Equals(field,value))
    {
        field = value;
        // extra code here
    }
}

使用

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

答案 1 :(得分:1)

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

这是一个例子

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

答案 2 :(得分:0)

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

或者,您可以沿ContextBoundObject路线前进,或Enterprise Libaries Policy Injectionhttp://msdn.microsoft.com/en-us/library/cc511729.aspx

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

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

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