Когда запускается конструктор пользовательского атрибута?


когда он запускается? Выполняется ли он для каждого объекта, к которому я его применяю, или только один раз? Может ли он что-нибудь сделать, или его действия ограничены?

4 68

4 ответа:

когда запускается конструктор? Попробуйте его с образцом:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Creating MyClass instance");
        MyClass mc = new MyClass();
        Console.WriteLine("Setting value in MyClass instance");
        mc.Value = 1;
        Console.WriteLine("Getting attributes for MyClass type");
        object[] attributes = typeof(MyClass).GetCustomAttributes(true);
    }

}

[AttributeUsage(AttributeTargets.All)]
public class MyAttribute : Attribute
{
    public MyAttribute()
    {
        Console.WriteLine("Running constructor");
    }
}

[MyAttribute]
class MyClass
{
    public int Value { get; set; }
}

и какой выход?

Creating MyClass instance
Setting value in MyClass instance
Getting attributes for MyClass type
Running constructor

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

конструктор выполняется каждый раз the GetCustomAttributes вызывается или всякий раз, когда какой-либо другой код вызывает конструктор напрямую (не то, чтобы есть веская причина для этого, но это тоже не невозможно).

обратите внимание, что по крайней мере в .NET 4.0 экземпляры атрибутов не кэшируется; каждый раз создается новый экземпляр GetCustomAttributes называется:

[Test]
class Program
{
    public static int SomeValue;

    [Test]
    public static void Main(string[] args)
    {
        var method = typeof(Program).GetMethod("Main");
        var type = typeof(Program);

        SomeValue = 1;

        Console.WriteLine(method.GetCustomAttributes(false)
            .OfType<TestAttribute>().First().SomeValue);
        // prints "1"

        SomeValue = 2;

        Console.WriteLine(method.GetCustomAttributes(false)
            .OfType<TestAttribute>().First().SomeValue);
        // prints "2"

        SomeValue = 3;

        Console.WriteLine(type.GetCustomAttributes(false)
            .OfType<TestAttribute>().First().SomeValue);
        // prints "3"

        SomeValue = 4;

        Console.WriteLine(type.GetCustomAttributes(false)
            .OfType<TestAttribute>().First().SomeValue);
        // prints "4"

        Console.ReadLine();
    }
}

[AttributeUsage(AttributeTargets.All)]
class TestAttribute : Attribute
{
    public int SomeValue { get; private set; }

    public TestAttribute()
    {
        SomeValue = Program.SomeValue;
    }
}

это не лучшая идея, чтобы атрибуты вели себя так, конечно. В крайней мере, обратите внимание, что GetCustomAttributes и не документировано вести себя так; на самом деле, что происходит в вышеуказанной программе не указано в документации.

установите точку останова отладчика внутри конструктора атрибутов и напишите некоторый код отражения, который читает эти атрибуты. Вы заметите, что объекты атрибутов не будут созданы, пока они не будут возвращены из API relfection. Атрибуты - это в классе. Они являются частью метаданных.

взгляните на это:

метаданные в исполняемом файле или DLL-хранилище:

  • A metadata token указание конструктора для вызова
  • доводы

когда я доберусь до этого раздела моей реализации CLI, я планирую ленивый вызов конструктора в первый раз GetCustomAttributes() для ICustomAttributeProvider. Если запрашивается определенный тип атрибута, я создам только те, которые необходимы для возврата этого типа.