Можно ли динамически добавлять атрибуты в C#?
-
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