Каковы атрибуты в .NET, для чего они хороши, и как я могу создать свои собственные атрибуты?
Что такое атрибуты в .NET?
Ответ 1
Метаданные. Данные о ваших объектах/методах/свойствах.
Например, я мог бы объявить Атрибут с именем: DisplayOrder, чтобы я мог легко контролировать, в каком порядке свойства должны отображаться в пользовательском интерфейсе. Затем я мог бы добавить его к классу и написать некоторые компоненты GUI, которые извлекают атрибуты и упорядочивают элементы UI соответствующим образом.
public class DisplayWrapper
{
private UnderlyingClass underlyingObject;
public DisplayWrapper(UnderlyingClass u)
{
underlyingObject = u;
}
[DisplayOrder(1)]
public int SomeInt
{
get
{
return underlyingObject .SomeInt;
}
}
[DisplayOrder(2)]
public DateTime SomeDate
{
get
{
return underlyingObject .SomeDate;
}
}
}
Таким образом, гарантируя, что SomeInt всегда отображается перед SomeDate при работе с моими пользовательскими компонентами GUI.
Однако вы увидите, что они чаще всего используются вне среды прямого кодирования. Например, конструктор Windows широко использует их, поэтому он знает, как обращаться с объектами, сделанными на заказ. Использование BrowsableAttribute примерно так:
[Browsable(false)]
public SomeCustomType DontShowThisInTheDesigner
{
get{/*do something*/}
}
Указывает конструктору не указывать это в доступных свойствах в окне "Свойства", например, во время разработки.
Вы также можете использовать их для генерации кода, операций перед компиляцией (таких как Post-Sharp) или операций во время выполнения, таких как Reflection.Emit. Например, вы можете написать немного кода для профилирования, который будет прозрачно упакован при каждом вызове, который ваш код делает, и умножит его. Вы можете "отказаться" от времени через атрибут, который вы помещаете в определенные методы.
public void SomeProfilingMethod(MethodInfo targetMethod, object target, params object[] args)
{
bool time = true;
foreach (Attribute a in target.GetCustomAttributes())
{
if (a.GetType() is NoTimingAttribute)
{
time = false;
break;
}
}
if (time)
{
StopWatch stopWatch = new StopWatch();
stopWatch.Start();
targetMethod.Invoke(target, args);
stopWatch.Stop();
HandleTimingOutput(targetMethod, stopWatch.Duration);
}
else
{
targetMethod.Invoke(target, args);
}
}
Объявить их легко, просто создайте класс, который наследуется от Attribute.
public class DisplayOrderAttribute : Attribute
{
private int order;
public DisplayOrderAttribute(int order)
{
this.order = order;
}
public int Order
{
get { return order; }
}
}
И помните, что когда вы используете атрибут, вы можете опустить суффикс "атрибут", компилятор добавит его для вас.
ПРИМЕЧАНИЕ. Атрибуты сами по себе ничего не делают - должен быть какой-то другой код, который их использует. Таким образом, компилятор заботится о паре, и некоторые фреймворки используют некоторые (например, NUnit ищет [TestFixture] в классе и [Test] в тестовом методе).
Поэтому при создании пользовательского атрибута следует учитывать, что он не повлияет на поведение вашего кода. Вам нужно будет написать другую часть, которая проверяет атрибуты (через отражение) и воздействует на них ".
Ответ 2
Многие люди ответили, но никто не упомянул об этом до сих пор...
Атрибуты используются с отражением. Отражение уже довольно медленное.
Очень полезно отметить ваши пользовательские атрибуты как классы sealed
, чтобы улучшить их производительность выполнения.
Также неплохо рассмотреть, где было бы целесообразно использовать такой атрибут и атрибут (!), чтобы указать это через AttributeUsage
. Список доступных атрибутов может удивить вас:
- Сборка
- Модуль
- Класс
- Struct
- Enum
- Конструктор
- Метод
- Свойство
- Поле
- Событие
- Интерфейс
- Параметр
- Делегат
- ReturnValue
- GenericParameter
- Все
Также замечательно, что атрибут AttributeUsage является частью сигнатуры атрибута AttributeUsage. Whoa для круговых зависимостей!
[AttributeUsageAttribute(AttributeTargets.Class, Inherited = true)]
public sealed class AttributeUsageAttribute : Attribute
Ответ 3
Атрибуты являются своего рода метаданными для маркировки классов. Это часто используется в WinForms, например, чтобы скрыть элементы управления от панели инструментов, но может быть реализовано в вашем собственном приложении, чтобы позволить экземплярам разных классов вести себя особым образом.
Начните с создания атрибута:
[AttributeUsage(AttributeTargets.Class, AllowMultiple=false, Inherited=true)]
public class SortOrderAttribute : Attribute
{
public int SortOrder { get; set; }
public SortOrderAttribute(int sortOrder)
{
this.SortOrder = sortOrder;
}
}
Все классы атрибутов должны иметь суффикс "Атрибут", чтобы быть действительным.
После того, как это сделано, создайте класс, который использует атрибут.
[SortOrder(23)]
public class MyClass
{
public MyClass()
{
}
}
Теперь вы можете проверить определенный класс ' SortOrderAttribute
(если он есть), выполнив следующие действия:
public class MyInvestigatorClass
{
public void InvestigateTheAttribute()
{
// Get the type object for the class that is using
// the attribute.
Type type = typeof(MyClass);
// Get all custom attributes for the type.
object[] attributes = type.GetCustomAttributes(
typeof(SortOrderAttribute), true);
// Now let make sure that we got at least one attribute.
if (attributes != null && attributes.Length > 0)
{
// Get the first attribute in the list of custom attributes
// that is of the type "SortOrderAttribute". This should only
// be one since we said "AllowMultiple=false".
SortOrderAttribute attribute =
attributes[0] as SortOrderAttribute;
// Now we can get the sort order for the class "MyClass".
int sortOrder = attribute.SortOrder;
}
}
}
Если вы хотите узнать больше об этом, вы всегда можете проверить MSDN, который имеет довольно хорошее описание.
Я надеюсь, что это помогло вам!
Ответ 4
Атрибут - это класс, который содержит немного функциональности, которую вы можете применить к объектам вашего кода. Чтобы создать его, создайте класс, который наследуется от System.Attribute.
Что касается того, что им хорошо... для них почти неограниченное использование.
Ответ 5
Атрибуты похожи на метаданные, применяемые к классам, методам или сборкам.
Они хороши для любого количества вещей (визуализация отладчика, маркировка вещей как устаревшая, маркировка вещей как сериализуемая, список бесконечен).
Создавать свои собственные пользовательские легко, как пирог. Начать здесь:
http://msdn.microsoft.com/en-us/library/sw480ze8(VS.71).aspx
Ответ 6
В проекте, над которым я сейчас работаю, есть набор объектов пользовательского интерфейса разных вкусов и редактор для сборки этих объектов для создания страниц для использования в основном приложении, немного похожих на конструктор форм в DevStudio. Эти объекты существуют в своей собственной сборке, и каждый объект является классом, производным от UserControl
, и имеет собственный атрибут. Этот атрибут определяется следующим образом:
[AttributeUsage (AttributeTargets::Class)]
public ref class ControlDescriptionAttribute : Attribute
{
public:
ControlDescriptionAttribute (String ^name, String ^description) :
_name (name),
_description (description)
{
}
property String ^Name
{
String ^get () { return _name; }
}
property String ^Description
{
String ^get () { return _description; }
}
private:
String
^ _name,
^ _description;
};
и я применяю его к классу, подобному этому:
[ControlDescription ("Pie Chart", "Displays a pie chart")]
public ref class PieControl sealed : UserControl
{
// stuff
};
о чем говорили предыдущие плакаты.
Чтобы использовать атрибут, редактор имеет Generic::List <Type>
, содержащий типы управления. Существует список, который пользователь может перетащить и перетащить на страницу, чтобы создать экземпляр элемента управления. Чтобы заполнить список, я получаю ControlDescriptionAttribute
для элемента управления и заполняю запись в списке:
// done for each control type
array <Object ^>
// get all the custom attributes
^attributes = controltype->GetCustomAttributes (true);
Type
// this is the one we're interested in
^attributetype = ECMMainPageDisplay::ControlDescriptionAttribute::typeid;
// iterate over the custom attributes
for each (Object ^attribute in attributes)
{
if (attributetype->IsInstanceOfType (attribute))
{
ECMMainPageDisplay::ControlDescriptionAttribute
^description = safe_cast <ECMMainPageDisplay::ControlDescriptionAttribute ^> (attribute);
// get the name and description and create an entry in the list
ListViewItem
^item = gcnew ListViewItem (description->Name);
item->Tag = controltype->Name;
item->SubItems->Add (description->Description);
mcontrols->Items->Add (item);
break;
}
}
Примечание: выше это С++/CLI, но это не сложно преобразовать в С# (да, я знаю, С++/CLI - мерзость, но это то, с чем мне приходится работать:-()
Вы можете поместить атрибуты на большинство вещей, и есть целый ряд предопределенных атрибутов. Вышеупомянутый редактор также ищет настраиваемые атрибуты свойств, которые описывают свойство и как его редактировать.
Как только вы получите всю идею, вы будете удивляться, как вы жили без них.
Ответ 7
Как сказано, атрибуты относительно легко создать. Другая часть работы - это создание кода, который его использует. В большинстве случаев вы будете использовать отражение во время выполнения, чтобы изменить поведение, основанное на наличии атрибута или его свойств. Существуют также сценарии, в которых вы будете проверять атрибуты на скомпилированном коде, чтобы сделать какой-то статический анализ. Например, параметры могут быть помечены как ненулевые, и инструмент анализа может использовать это как подсказку.
Использование атрибутов и знание соответствующих сценариев для их использования - основная часть работы.
Ответ 8
Атрибуты - это, по сути, биты данных, которые вы хотите присоединить к типам (классы, методы, события, перечисления и т.д.).
Идея заключается в том, что во время выполнения какой-либо другой тип /framework/tool запрашивает ваш тип информации в атрибуте и действует на него.
Итак, например, Visual Studio может запрашивать атрибуты стороннего элемента управления, чтобы выяснить, какие свойства элемента управления должны появиться на панели "Свойства" во время разработки.
Атрибуты также могут использоваться в Aspect Oriented Programming для ввода/манипулирования объектами во время выполнения на основе атрибутов, которые их украшают, и добавления объектов, не влияя на бизнес-логику объекта.
Ответ 9
Вы можете использовать пользовательские атрибуты как простой способ определить значения тегов в подклассах без необходимости повторять один и тот же код для каждого подкласса. Я натолкнулся на хороший краткий пример Джона Уотерса о том, как определять и использовать пользовательские атрибуты в вашем собственном коде.
Существует учебник по http://msdn.microsoft.com/en-us/library/aa288454(VS.71).aspx
Ответ 10
Чтобы начать создание атрибута, откройте исходный файл С#, введите attribute
и нажмите [TAB]. Он будет расширяться до шаблона для нового атрибута.
Ответ 11
Атрибуты также широко используются для аспектно-ориентированного программирования. В качестве примера рассмотрим проект PostSharp.