【问题标题】:Replace Property Setter method at runtime在运行时替换 Property Setter 方法
【发布时间】:2010-12-07 03:30:47
【问题描述】:

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

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

【问题讨论】:

    标签: c# reflection


    【解决方案1】:

    一种方法是使属性虚拟化,并在运行时通过反射发射创建一个覆盖属性的子类,并添加您的代码。但是,这是高级的,并且要求您始终确保创建子类(因此代码中没有“新”)。

    但是;我想知道简单地实现 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); }
    }
    

    【讨论】:

    • 这与我现在所拥有的非常接近,谢谢。这确实可以完成这项工作,但意味着我必须手动拦截所有呼叫。
    【解决方案2】:

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

    这里有一个例子

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

    【讨论】:

    • 这篇文章确实有点矫枉过正,但强调它可以做到,我会尝试这个但没有属性。谢谢,当我知道更多时,我会发布一些更新。
    【解决方案3】:

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

    您也可以选择ContextBoundObjectEnterprise Libaries Policy Injectionhttp://msdn.microsoft.com/en-us/library/cc511729.aspx

    请注意,ContextBoundObject 比 Castle 的动态代理要慢得多,但您不必将方法声明为虚拟的。策略注入仅允许您在调用建议之前或之后插入,因此无论出于何种原因反对它,您都无法停止调用。

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

    我个人正在开发我自己的动态代理,它允许用委托替换方法,但它还没有准备好成为众人瞩目的焦点。

    【讨论】:

      猜你喜欢
      • 2020-02-21
      • 1970-01-01
      • 2012-07-29
      • 2014-09-15
      • 1970-01-01
      • 2023-01-26
      • 2019-03-25
      • 1970-01-01
      • 2011-01-09
      相关资源
      最近更新 更多