Могут ли атрибуты быть добавлены динамически в C #? - PullRequest
140 голосов
/ 24 сентября 2008

Можно ли добавить атрибуты во время выполнения или изменить значение атрибута во время выполнения?

Ответы [ 10 ]

67 голосов
/ 24 сентября 2008

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

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

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

66 голосов
/ 24 сентября 2008

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

10 голосов
/ 24 сентября 2008

Ну, чтобы отличаться, я нашел статью, в которой есть ссылки на Reflection.Emit.

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

10 голосов
/ 24 сентября 2008

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

4 голосов
/ 24 сентября 2008

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

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

3 голосов
/ 24 сентября 2008

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

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

3 голосов
/ 24 сентября 2008

Если вам нужно что-то, чтобы иметь возможность добавлять динамически, атрибуты c # не подходят. Посмотрите на хранение данных в XML. Недавно я сделал проект, который я начал с атрибутов, но в итоге перешел на сериализацию с xml.

3 голосов
/ 24 сентября 2008

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

1 голос
/ 08 сентября 2017

Я очень старался с 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);
                }
            }
        }
0 голосов
/ 24 сентября 2008

В Java я раньше обходил это, используя карту и реализуя свой собственный подход к кодированию значения ключа.

http://developer.apple.com/documentation/Cocoa/Conceptual/KeyValueCoding/KeyValueCoding.html

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