什么时候是自定义属性的构造函数运行?
什么时候运行? 它是针对我应用的每个对象运行,还是只运行一次? 它可以做任何事情,或者其行动受到限制?
构造函数何时运行? 尝试一下样本:
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
所以,当我们开始检查属性时,运行属性构造函数。 请注意,该属性是从types中获取的,而不是types的实例。
每次调用GetCustomAttributes
时都会运行构造函数,或者其他代码直接调用构造函数(并非有充分的理由这样做,但也不是不可能)。
请注意,至less在.NET 4.0中,属性实例不会被caching ; 每次调用GetCustomAttributes
都会创build一个新实例:
[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; } }
当然,拥有属性的行为并不是最好的想法。 至less,请注意, GetCustomAttributes
没有被logging为这样的行为; 实际上,在上述程序中发生的事情并没有在文档中指定。
在属性构造器中设置一个debugging器断点,并编写一些读取这些属性的reflection代码。 你会注意到,属性对象将不会被创build,直到它们从重新获得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(); } }
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; } }
结果
Program started MyAttribute created with 15. 15 Program ended
但不要担心属性构造函数的性能。 他们是反思最快的部分:-P
可执行文件或DLL中的元数据存储:
- 指示要调用的构造函数的元数据标记
- 参数
当我到达CLI实现的那一部分时,我计划在第一次为ICustomAttributeProvider
调用GetCustomAttributes()
时懒惰地调用构造ICustomAttributeProvider
。 如果请求了特定的属性types,我将只构造返回该types所需的属性。