Вопрос

Что такое атрибуты в .NET, для чего они нужны и как создавать собственные атрибуты?

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

Решение

Метаданные.Данные о ваших объектах/методах/свойствах.

Например, я мог бы объявить атрибут под названием:DisplayOrder, чтобы я мог легко контролировать, в каком порядке свойства должны отображаться в пользовательском интерфейсе.Затем я мог бы добавить его в класс и написать несколько компонентов графического интерфейса, которые извлекают атрибуты и соответствующим образом упорядочивают элементы пользовательского интерфейса.

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 при работе с моими пользовательскими компонентами графического интерфейса.

Однако вы увидите, что они чаще всего используются за пределами среды прямого кодирования.Например, конструктор 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; }
    }
}

И помните, что когда вы используете атрибут, вы можете опустить суффикс «атрибут», компилятор добавит его за вас.

ПРИМЕЧАНИЕ: Атрибуты сами по себе ничего не делают — должен быть какой-то другой код, который их использует.Иногда этот код пишется за вас, но иногда вам приходится писать его самостоятельно.Например, компилятор C# заботится о некоторых, а некоторые платформы используют некоторые (например,NUnit ищет [TestFixture] в классе и [Test] в тестовом методе при загрузке сборки).
Поэтому при создании собственного атрибута имейте в виду, что он вообще не повлияет на поведение вашего кода.Вам нужно будет написать другую часть, которая проверяет атрибуты (посредством отражения) и действует на них.

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

Многие ответили, но пока никто об этом не упомянул...

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

Это очень стоит отметка ваших пользовательских атрибутов как sealed классы для улучшения их производительности во время выполнения.

Также неплохо подумать, где будет уместно использовать такой атрибут, и приписать свой атрибут (!), чтобы указать это через AttributeUsage.Список доступных вариантов использования атрибутов может вас удивить:

  • Сборка
  • Модуль
  • Сорт
  • Структура
  • Перечисление
  • Конструктор
  • Метод
  • Свойство
  • Поле
  • Событие
  • Интерфейс
  • Параметр
  • Делегат
  • Возвращаемое значение
  • Общий параметр
  • Все

Также здорово, что атрибут AttributeUsage является частью подписи атрибута AttributeUsage.Ого, круговые зависимости!

[AttributeUsageAttribute(AttributeTargets.Class, Inherited = true)]
public sealed class AttributeUsageAttribute : Attribute

Атрибуты — это своего рода метаданные для тегирования классов.Это часто используется в 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's 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 у которого довольно хорошее описание.
Надеюсь, это помогло вам!

Атрибут — это класс, содержащий некоторую функциональность, которую вы можете применить к объектам в своем коде.Чтобы создать его, создайте класс, который наследуется от System.Attribute.

А насчет того, чем они хороши...их применение практически безгранично.

http://www.codeproject.com/KB/cs/dotnetattributes.aspx

Атрибуты подобны метаданным, применяемым к классам, методам или сборкам.

Они хороши для любого количества вещей (визуализация отладчика, пометка вещей как устаревших, пометка вещей как сериализуемых, список бесконечен).

Создать свой собственный вариант проще простого.Начало здесь:

http://msdn.microsoft.com/en-us/library/sw480ze8(VS.71).aspx

В проекте, над которым я сейчас работаю, есть набор различных объектов пользовательского интерфейса и редактор для сборки этих объектов для создания страниц для использования в основном приложении, немного похожий на дизайнер форм в 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;
  }
}

Примечание:Выше приведено C ++/CLI, но не сложно преобразовать в C# (да, я знаю, C ++/CLI-это мерзость, но это то, с чем я должен работать :-()

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

Как только вы поймете всю идею, вы удивитесь, как вы раньше жили без них.

Как уже было сказано, атрибуты создать относительно легко.Другая часть работы — создание кода, который его использует.В большинстве случаев вы будете использовать отражение во время выполнения, чтобы изменить поведение в зависимости от наличия атрибута или его свойств.Существуют также сценарии, в которых вы проверяете атрибуты скомпилированного кода для проведения своего рода статического анализа.Например, параметры могут быть помечены как ненулевые, и инструмент анализа может использовать это как подсказку.

Использование атрибутов и знание соответствующих сценариев их использования — это основная часть работы.

Атрибуты — это, по сути, фрагменты данных, которые вы хотите прикрепить к своему типы (классы, методы, события, перечисления и т. д.)

Идея состоит в том, что во время выполнения какой-либо другой тип/фреймворк/инструмент будет запрашивать твой введите информацию в атрибут и действуйте в соответствии с ней.

Так, например, Visual Studio может запросить атрибуты стороннего элемента управления, чтобы выяснить, какие свойства элемента управления должны отображаться на панели «Свойства» во время разработки.

Атрибуты также можно использовать в аспектно-ориентированном программировании для внедрения объектов и манипулирования ими во время выполнения на основе атрибутов, которые их украшают, а также добавляют проверку, ведение журнала и т. д.к объектам, не затрагивая бизнес-логику объекта.

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

Есть учебник по адресу http://msdn.microsoft.com/en-us/library/aa288454(VS.71).aspx

Чтобы приступить к созданию атрибута, откройте исходный файл C#, введите attribute и нажмите [TAB].Он расширится до шаблона для нового атрибута.

Атрибуты также часто используются в аспектно-ориентированном программировании.Для примера этого посмотрите ПостШарп проект.

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