如何在 C# 中向类动态添加字段
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/646258/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I dynamically add a field to a class in C#
提问by Pavel Podlipensky
Is there any way to add Field
(or FieldInfo
, maybe this is the same) to a class at runtime?
有什么方法可以在运行时向类添加Field
(或者FieldInfo
,也许这是相同的)?
采纳答案by Mehrdad Afshari
You can't alter a class definition at runtime. However, you can create a new class that inherits from the original class (if it's not sealed
) and declares the field. You can do this by emitting the appropriate IL code using System.Reflection.Emit
.
您不能在运行时更改类定义。但是,您可以创建一个从原始类(如果不是sealed
)继承的新类并声明该字段。您可以通过使用System.Reflection.Emit
.
回答by Greg Beech
No, C# doesn't allow monkey-patching.
不,C# 不允许猴子修补。
You can generate newclasses using either CodeDOM or Reflection.Emit, but you can't modify existing ones.
您可以使用 CodeDOM 或 Reflection.Emit生成新类,但不能修改现有类。
回答by codekaizen
Not exactly.
不完全是。
However, you can implement ICustomTypeDescriptor to approximate it, and then just use a hashtable to store the fieldname/value pairs. A lot of the framework which uses reflection asks for ICustomTypeDescriptor first.
但是,您可以实现 ICustomTypeDescriptor 来近似它,然后只需使用哈希表来存储字段名/值对。许多使用反射的框架首先要求 ICustomTypeDescriptor。
回答by Daniel Earwicker
Not until C# 4.0 which adds dynamic lookup and is based on the CLR 4.0 which incorporates the DLR, and then it will not strictly be adding to a class, as classes won't be in the picture.
直到 C# 4.0 添加动态查找并基于包含 DLR 的 CLR 4.0,然后它才不会严格添加到类中,因为类不会出现在图片中。
回答by JaredPar
C# does not allow it because all of it's classes are based on Metadata. The CLR(not C#) disallows the adding of fields to metadata at runtime (1). This is the only way that C# would be able to add a field at runitme.
C# 不允许它,因为它的所有类都基于元数据。的CLR(未C#)不允许字段的在运行时:(1)增加的元数据。这是 C# 能够在 runitme 添加字段的唯一方法。
This is unlike dynamic langauges such as IronPython which essentially don't have concrete metadata classes. They have more dynamic structures which can be altereted at runtime. I believe IronPython simply keeps it's members (fields and methods) in what amounts to a hashtable that can be easily altered at runtime.
这与 IronPython 等动态语言不同,后者基本上没有具体的元数据类。它们具有更多动态结构,可以在运行时更改。我相信 IronPython 只是将它的成员(字段和方法)保留在相当于一个可以在运行时轻松更改的哈希表中。
In C# 3.0, your best resource is to use Reflection.Emit. But this will generate an entirely new class vs. altering an existing one.
在 C# 3.0 中,最好的资源是使用 Reflection.Emit。但这将生成一个全新的类,而不是改变现有的类。
(1) There are certain APIs such as the profiling APIs or ENC that allow this but I'm not sure if their capabalities expand to adding fields.
(1) 有某些 API,例如分析 API 或 ENC,允许这样做,但我不确定它们的功能是否扩展到添加字段。
回答by Tomas Petricek
as others already said, this isn't possible. What is the reason for your question? If you need to store some additional data in the class dynamically, then you could probably just use dictionary:
正如其他人已经说过的,这是不可能的。你问这个问题的原因是什么?如果你需要在类中动态存储一些额外的数据,那么你可能只使用字典:
class My {
Dictionary<string, object> data;
public My() { data = new Dictionary<string, object>(); }
}
.. but it really depends on what you actually want to achieve?
..但这真的取决于你真正想要实现的目标吗?
回答by yoel halb
See this questionfor a simple way to do it in C# 4.0, by casting an ExpandoObject
as an IDictionary
, which causes the values added to the dictionary to become properties of the object. I demonstrate this in another answer of mineshowing that they actually become properties.
有关在 C# 4.0 中执行此操作的简单方法,请参阅此问题,方法是将 an 转换ExpandoObject
为 an IDictionary
,这会导致添加到字典中的值成为对象的属性。我在我的另一个答案中证明了这一点,表明它们实际上成为了属性。
However, this is only possible with an instance of ExpandoObject
or by sub-classing DynamicObject
.
但是,这仅适用于ExpandoObject
或 子类的实例DynamicObject
。
It may also be possible to use with other classes if they implement IDynamicMetaObjectProvider
, but I think there is too much work involved to get it to work properly.
如果其他类实现了IDynamicMetaObjectProvider
,也可以与其他类一起使用,但我认为要使其正常工作需要做太多工作。
回答by Max Hodges
Perhaps you could use the Decorator pattern.
也许您可以使用装饰器模式。
In object-oriented programming, the decorator pattern is a design pattern that allows behavior to be added to an individual object, either statically or dynamically, without affecting the behavior of other objects from the same class.
在面向对象的编程中,装饰器模式是一种设计模式,它允许将行为静态或动态地添加到单个对象中,而不会影响来自同一类的其他对象的行为。