2008-09-24 2 views

ответ

63

Атрибуты являются статическими метаданными. Ассембли, модули, типы, члены, параметры и возвращаемые значения не являются первоклассными объектами в C# (например, класс System.Type - это просто отраженное представление типа). Вы можете получить экземпляр атрибута для типа и изменить свойства, если они доступны для записи, но это не повлияет на атрибут, поскольку он применяется к типу.

3

Я так не верю. Даже если я ошибаюсь, лучшее, на что вы можете надеяться, это добавить их к целому типу, а не к экземпляру типа.

+21

ТипDescriptor.AddAttributes (Object, Attribute []) добавляет атрибуты уровня класса к экземпляру целевого компонента. – 2008-11-10 12:25:46

4

Нет, это не так.

Атрибуты являются метаданными и хранятся в двоичной форме в скомпилированной сборке (поэтому вы можете использовать только простые типы).

9

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

3

Если вам нужно что-то, что можно добавить динамически, атрибуты C# - это не так. Посмотрите на хранение данных в xml. Недавно я сделал проект, в котором я начал w/attributes, но в конечном итоге перешел к сериализации w/xml.

3

Зачем вам это нужно? Атрибуты дают дополнительную информацию для размышлений, но если вы извне знаете, какие свойства вы хотите, они вам не нужны.

Вы можете хранить метаданные внешне относительно легко в базе данных или файле ресурсов.

+1

Удаление котла. Не было бы удобно, если бы у вас был класс, автоматически генерирующий атрибуты на основе кода внутри класса? Я пытаюсь выяснить что-то подобное, чтобы уменьшить шаблон в объектах CLR SQL. Было бы легко на других языках ... см. Http://www.paulgraham.com/avg.html – 2011-05-31 01:30:52

65

Это действительно зависит от того, что именно вы пытаетесь выполнить.

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

Насколько я знаю, элемент управления PropertyGrid и визуальная студия дизайна являются единственными вещами в BCL, которые потребляют материал TypeDescriptor. Фактически, именно так они делают примерно половину того, что им действительно нужно делать.

+5

На самом деле, большинство привязки данных использует `TypeDescriptor` - не просто` PropertyGrid`. – 2010-09-09 05:23:16

+1

Любое обходное решение для добавления атрибутов свойств-метаданных в проекте Silverlight (где `TypeDescriptor` и` TypeDescriptionProvider` не реализованы? – Shimmy 2012-02-25 22:01:21

+0

Важно отметить, что TypeDescriptor.GetAttributes() не обрабатывает повторяющиеся атрибуты. Он выбирает только последний из атрибут type. Ex `[Attr (1), Attr (2), Attr (3)]` only `Attr (3)` найден. – ohmusama 2013-05-22 17:45:58

10

Ну, просто чтобы быть другим, я нашел статью, ссылающуюся на Reflection.Emit, чтобы сделать это.

Вот ссылка: http://www.codeproject.com/KB/cs/dotnetattributes.aspx, вы также захотите ознакомиться с некоторыми комментариями в нижней части статьи, поскольку обсуждаются возможные подходы.

0

Я очень старался с System.ComponentModel.TypeDescriptor без успеха. Это не означает, что он не может работать, но я хотел бы видеть код для этого.

В части счетчика я хотел изменить некоторые значения атрибута. Я сделал 2 функции, которые отлично работают для этой цели.

 // ************************************************************************ 
     public static void SetObjectPropertyDescription(this Type typeOfObject, string propertyName, string description) 
     { 
      PropertyDescriptor pd = TypeDescriptor.GetProperties(typeOfObject)[propertyName]; 
      var att = pd.Attributes[typeof(DescriptionAttribute)] as DescriptionAttribute; 
      if (att != null) 
      { 
       var fieldDescription = att.GetType().GetField("description", BindingFlags.NonPublic | BindingFlags.Instance); 
       if (fieldDescription != null) 
       { 
        fieldDescription.SetValue(att, description); 
       } 
      } 
     } 

     // ************************************************************************ 
     public static void SetPropertyAttributReadOnly(this Type typeOfObject, string propertyName, bool isReadOnly) 
     { 
      PropertyDescriptor pd = TypeDescriptor.GetProperties(typeOfObject)[propertyName]; 
      var att = pd.Attributes[typeof(ReadOnlyAttribute)] as ReadOnlyAttribute; 
      if (att != null) 
      { 
       var fieldDescription = att.GetType().GetField("isReadOnly", BindingFlags.NonPublic | BindingFlags.Instance); 
       if (fieldDescription != null) 
       { 
        fieldDescription.SetValue(att, isReadOnly); 
       } 
      } 
     }