Можно ли динамически добавлять атрибуты в C#?

StackOverflow https://stackoverflow.com/questions/129285

  •  02-07-2019
  •  | 
  •  

Вопрос

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

Это было полезно?

Решение

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

Другие советы

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

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

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

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

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

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

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

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

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

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

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

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

Я очень старался с 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);
                }
            }
        }

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top