如何在 C# 运行时向类添加属性?

Posted

技术标签:

【中文标题】如何在 C# 运行时向类添加属性?【英文标题】:How Can I add properties to a class on runtime in C#? 【发布时间】:2013-01-21 09:36:40 【问题描述】:

我有一堂课:

class MyClass 


...
MyClass c = new MyClass();

是否可以在运行时向此类添加属性/字段?

我不知道它们在编译时的类型或名称是什么,而且它们没有我可以使用的通用接口。

伪例子:

 Add property named "Prop1" [type System.Int32]
 Add property named "Prop900" [type System.String]

我已经读过this question,但它使用接口

提前致谢。

【问题讨论】:

然后到处通过反射访问它们? Dictionary<string, object> 怎么样? @HenkHolterman 是的 Henk 稍后我使用 MyClass.GetType().GetProperties() 访问它们 您需要它用于什么用例? ICustomeTypeDescriptor呢? @RoyiNamir:反射与 IL 修改无关——这就是您想要实现的目标。 为什么要通过直接跳入可能最糟糕的用途来“学习”反射? 【参考方案1】:

是的,您可以使用ExpandoObject 类来实现这一点。

dynamic expando = new ExpandoObject();
expando.Prop1 = 10;
expando.Prop900 = string.Empty;

【讨论】:

它内部使用字典实现。我需要带有属性的纯类。 GetType().GetProperties() 的效率可能不如字典。 有什么方法可以同时使用 ExpandoObject 指定这些属性的数据类型? 你的方案是什么? Acutally Prop1 ... Prop900 不是属性,这些是字典项,因为 expanto.GetType().GetProperties() 不返回这些属性。【参考方案2】:

您不能在运行时使用新成员扩展现有类。但是,您可以使用 System.Reflection.Emit 创建一个新类,并将现有类作为基类。

typeBuilder.SetParent(typeof(MyClass));
typeBuilder.DefineProperty("Prop1", ..., typeof(System.Int32), null);
...

有关完整示例,请参阅 TypeBuilder.DefineProperty Method (String, PropertyAttributes, Type, Type[])。

【讨论】:

我已经成功了。谢谢。 (就是这样)。感谢您回答实际问题。【参考方案3】:

我想你误解了什么是反射。反射不允许您更改正在运行的代码。它可以让您阅读自己的代码,甚至可以运行该代码。

使用 Reflection.Emit,您可以编写一个全新的程序集,然后将其加载到内存中。

但是,您不能在运行时更改类。想象一下,你有一个 Foo 类,你实例化了一大堆它们,然后决定改变这个类。

你已经实例化的所有 Foo 应该怎么办?

但是,您可以使用 Reflection.Emit 创建一个继承 Foo 的新类,称为 Bar,然后将您需要的任何内容添加到该类中。

或者,如果您想在编译时间之后但在运行时间之前以编程方式将属性添加到类,您可以查看 IL Weaving/AOP。如果您对此感兴趣,我建议您查看PostSharp 或Fody。

【讨论】:

以上是关于如何在 C# 运行时向类添加属性?的主要内容,如果未能解决你的问题,请参考以下文章

在运行时向对象添加属性,并保存到数据库

我可以使用类别和运行时向 UIScrollView 添加 BOOL 类型属性“isScrolling”吗?

在 Visual Studio 中添加运行时断点如何工作?

在运行时向 Gridview 动态添加行

在运行时向 Enum 添加值

在 AsyncTask 运行时向 TextView 添加文本