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

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

Ответ 1

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

Ответ 2

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

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

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

Ответ 3

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

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

Ответ 4

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

Ответ 5

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

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

Ответ 6

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

Ответ 7

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

Ответ 8

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

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

Ответ 9

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