何时自定义属性的构造函数运行?

dev*_*ium 73 .net c# vb.net attributes constructor

什么时候运行?它是针对我应用它的每个对象运行的,还是只运行一次?它可以做任何事情,或者它的行为受到限制吗?

Fre*_*örk 65

构造函数何时运行?尝试一下样品:

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; }
}
Run Code Online (Sandbox Code Playgroud)

什么是输出?

Creating MyClass instance
Setting value in MyClass instance
Getting attributes for MyClass type
Running constructor
Run Code Online (Sandbox Code Playgroud)

因此,当我们开始检查属性时,将运行属性构造函数.请注意,该属性是从类型中获取的,而不是类型的实例.

  • 请注意,如果多次调用GetCustomAttributes,则构造函数会多次运行. (16认同)
  • 您还可以在属性的构造函数中添加代码,以便根据上下文更改值.如果属性被缓存,则无法执行此操作. (3认同)

Rom*_*kov 15

构造函数运行每次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;
    }
}
Run Code Online (Sandbox Code Playgroud)

当然,让属性表现得不是最好的主意.最起码,请注意,GetCustomAttributes没有记录在案,以这样的表现; 事实上,上述程序中发生的事情未在文档中指定.


Chr*_*ser 6

在属性构造函数中设置调试器断点,并编写一些读取这些属性的反射代码.您会注意到,在从relfection API返回属性对象之前,不会创建它们.属性是每个类.它们是元数据的一部分.

看看这个:

Program.cs中

using System;
using System.Linq;
[My(15)]
class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Program started");
        var ats =
            from a in typeof(Program).GetCustomAttributes(typeof(MyAttribute), true)
            let a2 = a as MyAttribute
            where a2 != null
            select a2;

        foreach(var a in ats)
            Console.WriteLine(a.Value);

        Console.WriteLine("Program ended");
        Console.ReadLine();
    }
}
Run Code Online (Sandbox Code Playgroud)

MyAttribute.cs

using System;
[AttributeUsage(validOn : AttributeTargets.Class)]
public class MyAttribute : Attribute
{
    public MyAttribute(int x)
    {
        Console.WriteLine("MyAttribute created with {0}.", x);
        Value = x;
    }

    public int Value { get; private set; }    
}
Run Code Online (Sandbox Code Playgroud)

结果

Program started
MyAttribute created with 15.
15
Program ended
Run Code Online (Sandbox Code Playgroud)

但是不要担心属性构造函数的性能.它们是反思中最快的部分:-P