17

我有一堂课:

class MyClass 
{
}
...
MyClass c = new MyClass();

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

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

伪示例:

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

我已经读过这个问题,但它使用界面

提前致谢。

4

3 回答 3

45

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

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

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

于 2013-02-06T08:47:08.437 回答
6

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

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

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

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

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

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

于 2013-02-06T09:09:32.620 回答
2

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

dynamic expando = new ExpandoObject();
expando.Prop1 = 10;
expando.Prop900 = string.Empty;
于 2013-02-06T08:45:20.220 回答