Как я могу динамически добавить поле в класс в C # - PullRequest
22 голосов
/ 14 марта 2009

Есть ли способ добавить Field (или FieldInfo, возможно, это то же самое) к классу во время выполнения?

Ответы [ 8 ]

25 голосов
/ 14 марта 2009

Вы не можете изменить определение класса во время выполнения. Однако вы можете создать новый класс, который наследует от исходного класса (если это не sealed) и объявляет поле. Вы можете сделать это, выдав соответствующий код IL, используя System.Reflection.Emit.

7 голосов
/ 14 марта 2009

C # не позволяет этого, потому что все его классы основаны на метаданных. CLR (не C #) запрещает добавление полей к метаданным во время выполнения (1). Это единственный способ, с помощью которого C # может добавить поле в runitme.

Это не похоже на динамические языки, такие как IronPython, которые по существу не имеют конкретных классов метаданных. Они имеют более динамичные структуры, которые могут быть изменены во время выполнения. Я считаю, что IronPython просто хранит свои элементы (поля и методы) в том, что составляет хеш-таблицу, которую можно легко изменить во время выполнения.

В C # 3.0 ваш лучший ресурс - использовать Reflection.Emit. Но это создаст совершенно новый класс по сравнению с изменением существующего.

(1) Существуют определенные API, такие как API профилирования или ENC, которые позволяют это, но я не уверен, расширяются ли их возможности для добавления полей.

6 голосов
/ 14 марта 2009

Нет, C # не разрешает исправление обезьян .

Вы можете генерировать новые классы, используя CodeDOM или Reflection.Emit, но вы не можете изменять существующие.

1 голос
/ 10 августа 2012

См. этот вопрос для простого способа сделать это в C # 4.0, приведя ExpandoObject в качестве IDictionary, что приводит к тому, что добавленные в словарь значения становятся свойствами объекта. Я демонстрирую это в другом моем ответе , показывающем, что они действительно становятся свойствами.

Однако это возможно только с экземпляром ExpandoObject или подклассом DynamicObject.

Может также быть возможно использовать с другими классами, если они реализуют IDynamicMetaObjectProvider, но я думаю, что слишком много работы, чтобы заставить его работать должным образом.

1 голос
/ 14 марта 2009

как уже говорили другие, это невозможно. В чем причина вашего вопроса? Если вам нужно динамически хранить некоторые дополнительные данные в классе, то вы можете просто использовать словарь:

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

.. но это действительно зависит от того, чего вы на самом деле хотите достичь?

1 голос
/ 14 марта 2009

Только до C # 4.0, который добавляет динамический поиск и основан на CLR 4.0, который включает DLR, и тогда он не будет строго добавляться к классу, так как классы не будут на рисунке.

1 голос
/ 14 марта 2009

Не совсем.

Однако вы можете реализовать ICustomTypeDescriptor для его аппроксимации, а затем просто использовать хеш-таблицу для хранения пар имя / значение. Многие фреймворки, использующие рефлексию, сначала запрашивают ICustomTypeDescriptor.

0 голосов
/ 23 февраля 2013

Возможно, вы могли бы использовать шаблон Decorator.

В объектно-ориентированном программировании шаблон декоратора - это шаблон проектирования, который позволяет добавлять поведение к отдельному объекту, статически или динамически, без влияния на поведение других объектов того же класса.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...