Создание пользовательских атрибутов

72

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

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

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

// Создаем атрибут
    public sealed class UInfoAttribute : System.Attribute
    {
        public string Desc;
        public UInfoAttribute() { }
        public UInfoAttribute(string str)
        {
            Desc = str;
        }
    }

Как только класс атрибута будет определен, атрибут можно присоединить к элементу. Атрибут указывается перед тем элементом, к которому он присоединяется, и для этого его конструктор заключается в квадратные скобки.

По умолчанию действие специальных атрибутов может распространяться на практически любой аспект кода (методы, классы, свойства и т.д.). В одних случаях подобное поведение оказывается именно тем, что нужно, но в других, однако, может потребоваться создать вместо этого специальный атрибут, действие которого бы распространялось только на избранные элементы кода. Чтобы ограничить область действия специального атрибута, необходимо применить к его определению атрибут [AttributeUsage]. Атрибут [AttributeUsage] позволяет предоставлять (посредством операции OR) любую комбинацию значений из перечисления AttributeTargets:

//В этом перечислении описаны целевые объекты,
//на которые распространяется действие атрибута.
public enum AttributeTargets
{
   All, Assembly, Class, Constructor,
   Delegate, Enum, Event, Field, GenericParameter,
   Interface, Method, Module, Parameter,
   Property, ReturnValue, Struct
}

Более того, атрибут [AttributeUsage] также позволяет дополнительно устанавливать свойство AllowMultiple, которое указывает, может ли атрибут применяться к одному и тому же элементу более одного раза (значением по умолчанию этого свойства является false). Помимо этого он также позволяет указывать, должен ли атрибут наследоваться производными классами, за счет применения именованного свойства Inherited (значением по умолчанию этого свойства является true).

Ниже представлен пример создания пользовательских атрибутов:

using System;
using System.Reflection;

namespace ConsoleApplication1
{
    // Создаем атрибут
    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field)]
    public sealed class UInfoAttribute : System.Attribute
    {
        public string Desc;
        public UInfoAttribute() { }
        public UInfoAttribute(string str)
        {
            Desc = str;
        }
    }

    class Program
    {
        [UInfo(Desc = "Главный метод программы")]
        static void Main()
        {
            Type t = typeof(UInfoAttribute);

            object[] obj = t.GetCustomAttributes(false);
            foreach (object o in obj)
                Console.WriteLine(o);

            Console.ReadLine();
        }
    }
}
Пройди тесты
Лучший чат для C# программистов