【问题标题】:How can I dynamically add a field to a class in C#如何在 C# 中动态地将字段添加到类中
【发布时间】:2010-10-13 08:58:44
【问题描述】:

有没有办法在运行时将Field(或FieldInfo,也许是一样的)添加到类中?

【问题讨论】:

标签: c# reflection


【解决方案1】:

不,C# 不允许monkey-patching

您可以使用 CodeDOM 或 Reflection.Emit 生成新的类,但不能修改现有的。

【讨论】:

  • 这叫猴子补丁?这个词是从哪里来的?
  • 不知道它来自哪里,但我添加了一个指向维基百科条目的链接。
  • 猴子补丁是一个来自 Ruby 的术语。杰夫·阿特伍德几年前在一篇博文中写过。
【解决方案2】:

您不能在运行时更改类定义。但是,您可以创建一个继承自原始类的新类(如果它不是sealed)并声明该字段。您可以通过使用System.Reflection.Emit 发出适当的IL 代码来做到这一点。

【讨论】:

    【解决方案3】:

    不完全是。

    但是,您可以实现 ICustomTypeDescriptor 来近似它,然后只需使用哈希表来存储字段名/值对。许多使用反射的框架首先要求 ICustomTypeDescriptor。

    【讨论】:

    • 谢谢,我已经尝试过这种方法,但它对我不起作用。我正在尝试实现 IExpando 接口以允许 javascript 代码调用我的 C# 类中不存在的字段。例如,var o = new ActiveXObject('mCom'); o.ArbitraryField = "Foo";请注意,我的班级不存在 ArbitraryField。
    • 您是否尝试过实现 IReflect?这是实现 IDispatch/IExpando 以与动态语言互操作的方法(至少在 C# 4.0 之前)。 msdn.microsoft.com/en-us/library/… 我已经用哈希表实现了这一点,它运行良好
    【解决方案4】:

    直到 C# 4.0 添加了动态查找并基于包含 DLR 的 CLR 4.0,然后它不会严格添加到类中,因为类不会出现在图片中。

    【讨论】:

    • 我认为这在 C# 4.0 中是不可能的。我认为您将无法更改现有类型。但是,我可以想象您可以创建一些动态对象(例如,来自 Ruby)并对其进行更改。
    • 这就是我所说的“不严格添加到课程中,因为课程不会出现在图片中”。相反,“动态”引用的各个对象将能够接受分配给以前不存在的属性,并通过动态添加属性来处理这个问题。
    【解决方案5】:

    C# 不允许这样做,因为它的所有类都基于元数据。 CLR(不是 C#)不允许在运行时向元数据添加字段 (1)。这是 C# 能够在 runitme 添加字段的唯一方法。

    这与 IronPython 等动态语言不同,后者本质上没有具体的元数据类。它们有更多的动态结构,可以在运行时改变。我相信 IronPython 只是将它的成员(字段和方法)保存在相当于一个可以在运行时轻松更改的哈希表中。

    在 C# 3.0 中,最好的资源是使用 Reflection.Emit。但这将生成一个全新的类,而不是改变现有的类。

    (1) 某些 API(例如分析 API 或 ENC)允许这样做,但我不确定它们的功能是否扩展到添加字段。

    【讨论】:

      【解决方案6】:

      正如其他人已经说过的,这是不可能的。你的问题的原因是什么?如果您需要在类中动态存储一些额外的数据,那么您可能只使用字典:

      class My { 
         Dictionary<string, object> data;
         public My() { data = new Dictionary<string, object>(); }
      }
      

      .. 但这真的取决于你真正想要达到的目标?

      【讨论】:

      • 我的目标是实现 IExpando 接口。我的超级目标是允许 javascript 代码以“javascript 方式”动态地向 ActiveX 对象添加字段。例如, var myobj = new ActiveXObject('server.object'); myobj.ArbitraryField = "某事";请注意 ArbirtaryField 不存在
      【解决方案7】:

      请参阅this question 了解在 C# 4.0 中执行此操作的简单方法,将ExpandoObject 强制转换为IDictionary,这会使添加到字典中的值成为对象的属性。我在another answer of mine 中演示了这一点,表明它们实际上变成了属性。

      但是,这只能通过 ExpandoObject 的实例或通过子类化 DynamicObject 来实现。

      如果其他类实现了IDynamicMetaObjectProvider,也可以与其他类一起使用,但我认为要使其正常工作涉及到太多工作。

      【讨论】:

        【解决方案8】:

        也许你可以使用装饰器模式。

        在面向对象的编程中,装饰器模式是一种设计模式,它允许将行为静态或动态添加到单个对象,而不会影响同一类中其他对象的行为。

        http://www.dofactory.com/Patterns/PatternDecorator.aspx

        【讨论】:

          猜你喜欢
          • 2017-12-06
          • 2016-07-12
          • 2014-03-22
          • 1970-01-01
          • 2019-12-24
          • 2012-08-14
          • 2016-12-20
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多