Как я могу динамически добавлять поле в класс в С#
Есть ли способ добавить Field
(или FieldInfo
, может быть, это то же самое) к классу во время выполнения?
Ответы
Ответ 1
Вы не можете изменить определение класса во время выполнения. Однако вы можете создать новый класс, который наследует от исходного класса (если он не sealed
) и объявляет это поле. Вы можете сделать это, испустив соответствующий IL-код, используя System.Reflection.Emit
.
Ответ 2
Нет, С# не разрешает обезвреживание обезьян.
Вы можете создавать новые классы, используя либо CodeDOM, либо Reflection.Emit, но вы не можете изменять существующие.
Ответ 3
С# не позволяет этого, потому что все его классы основаны на метаданных. CLR (не С#) запрещает добавление полей в метаданные во время выполнения (1). Это единственный способ, которым С# мог бы добавить поле в runitme.
Это не похоже на динамические langauges, такие как IronPython, которые по существу не имеют конкретных классов метаданных. Они имеют более динамические структуры, которые могут быть изменены во время выполнения. Я считаю, что IronPython просто сохраняет его членами (полями и методами) в том, что составляет хэш-таблицу, которую можно легко изменить во время выполнения.
В С# 3.0 ваш лучший ресурс - использовать Reflection.Emit. Но это создаст совершенно новый класс и изменит существующий.
(1) Существуют определенные API, такие как API профилирования или ENC, которые позволяют это, но я не уверен, что их возможности расширяются до добавления полей.
Ответ 4
Не совсем.
Однако вы можете реализовать ICustomTypeDescriptor для его приближения, а затем просто использовать хэш-таблицу для хранения пар имя/значение. Многие рамки, использующие отражение, сначала запрашивают ICustomTypeDescriptor.
Ответ 5
Пока С# 4.0, который добавляет динамический поиск и основан на CLR 4.0, который включает DLR, а затем он не будет строго добавляться к классу, поскольку классы не будут отображаться.
Ответ 6
как уже говорили другие, это невозможно. В чем причина вашего вопроса? Если вам нужно хранить некоторые дополнительные данные в классе динамически, то вы, вероятно, можете просто использовать словарь:
class My {
Dictionary<string, object> data;
public My() { data = new Dictionary<string, object>(); }
}
.. но это действительно зависит от того, чего вы на самом деле хотите достичь?
Ответ 7
См. этот вопрос для простого способа сделать это в С# 4.0, выполнив ExpandoObject
как IDictionary
, что приводит к добавлению значений в словарь, чтобы стать свойствами объекта. Я демонстрирую это в еще одном моем ответе, показывающем, что они фактически становятся собственностью.
Однако это возможно только с экземпляром ExpandoObject
или путем подклассификации DynamicObject
.
Можно также использовать другие классы, если они реализуют IDynamicMetaObjectProvider
, но я думаю, что слишком много работы, чтобы заставить его работать правильно.
Ответ 8
Возможно, вы можете использовать шаблон Decorator.
В объектно-ориентированном программировании шаблон декоратора представляет собой шаблон проектирования, который позволяет добавлять поведение к отдельному объекту, статически или динамически, не влияя на поведение других объектов из того же класса.
http://www.dofactory.com/Patterns/PatternDecorator.aspx