什么时候运行?它是针对我应用它的每个对象运行的,还是只运行一次?它可以做任何事情,或者它的行为受到限制吗?
答案 0 :(得分: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; }
}
输出是什么?
Creating MyClass instance
Setting value in MyClass instance
Getting attributes for MyClass type
Running constructor
因此,当我们开始检查属性时,会运行属性构造函数。请注意,该属性是从类型中获取的,而不是类型的实例。
答案 1 :(得分:14)
构造函数运行每次调用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
不记录的行为如下;事实上,上述程序中发生的事情未在文档中指定。
答案 2 :(得分:6)
在属性构造函数中设置调试器断点,并编写一些读取这些属性的反射代码。您会注意到,在从relfection API返回属性对象之前,不会创建它们。属性是每个类。它们是元数据的一部分。
看看这个:
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();
}
}
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; }
}
Program started
MyAttribute created with 15.
15
Program ended
但是不要担心属性构造函数的性能。它们是反思中最快的部分:-P
答案 3 :(得分:4)
可执行文件或DLL中的元数据存储:
当我到达CLI实现的那一部分时,我计划在第一次为GetCustomAttributes()
调用ICustomAttributeProvider
时调用构造函数。如果请求了特定的属性类型,我将只构造返回该类型所需的属性类型。