C# 何时为自定义属性';什么是构造函数运行?

C# 何时为自定义属性';什么是构造函数运行?,c#,.net,vb.net,constructor,attributes,C#,.net,Vb.net,Constructor,Attributes,什么时候开始?它是针对我应用它的每个对象运行,还是只运行一次?它能做什么,或者它的动作受到限制吗?构造函数什么时候运行?请使用以下示例进行尝试: class Program { static void Main(string[] args) { Console.WriteLine("Creating MyClass instance"); MyClass mc = new MyClass(); Console.WriteLine("

什么时候开始?它是针对我应用它的每个对象运行,还是只运行一次?它能做什么,或者它的动作受到限制吗?

构造函数什么时候运行?请使用以下示例进行尝试:

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

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

可执行文件或DLL存储中的元数据:

  • 指示要调用的构造函数的元数据标记
  • 争论

当我进入CLI实现的那一部分时,我计划在第一次为
ICCustomAttributeProvider
调用
GetCustomAttributes()
时延迟调用构造函数。如果请求特定的属性类型,我将只构造返回该类型所需的属性。

在属性构造函数内设置调试器断点,并编写一些读取这些属性的反射代码。您会注意到,属性对象只有在从重新感染API返回后才会创建。属性是每个类的。它们是元数据的一部分

看看这个:

Program.cs MyAttribute.cs 结果
但是不要担心属性构造函数的性能。它们是反射的最快部分:-P

每次调用

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;
    }
}
[测试]
班级计划
{
公共价值观;
[测试]
公共静态void Main(字符串[]args)
{
var方法=typeof(Program).GetMethod(“Main”);
变量类型=类型(程序);
SomeValue=1;
Console.WriteLine(method.GetCustomAttributes(false)
.OfType().First().SomeValue);
//打印“1”
SomeValue=2;
Console.WriteLine(method.GetCustomAttributes(false)
.OfType().First().SomeValue);
//打印“2”
SomeValue=3;
Console.WriteLine(type.GetCustomAttributes(false)
.OfType().First().SomeValue);
//打印“3”
SomeValue=4;
Console.WriteLine(type.GetCustomAttributes(false)
.OfType().First().SomeValue);
//打印“4”
Console.ReadLine();
}
}
[属性设置(AttributeTargets.All)]
类TestAttribute:属性
{
public int SomeValue{get;private set;}
公共遗嘱属性()
{
SomeValue=Program.SomeValue;
}
}

当然,让属性像这样运行并不是最好的主意。至少,请注意,
GetCustomAttributes
而不是记录为这样的行为;事实上,上述程序中发生的事情并没有在文档中指定。

请注意,如果多次调用GetCustomAttributes,则构造函数会运行多次。是的,这一点值得指出;属性没有缓存(与我记忆中在应用程序运行时缓存的类型对象相反)。有人知道为什么属性对象没有缓存吗?@Matt:我不知道,但我的猜测是,类型对象的使用频率足以让投资缓存它们变得有趣,而属性可能不是这样。但我只是在猜测,你也可以在属性的构造函数中添加代码,例如根据上下文更改值。如果属性被缓存,你就不能这么做。该死!在VS 2010中尝试过这样做,但是没有ReSharper XD,我完全迷路了。这就是它的行为方式(动词“get”意味着动作)。GetCustomAttributes每次都必须返回新副本。这是确保在属性的构造函数中执行代码的唯一方法,即检查相关上下文。对于动态程序集、拦截和其他一切,我们无法知道自上次调用以来会发生什么变化。它甚至可能基于实时设置返回一组不同的属性。我确实同意,这种行为显然是设计出来的,支持一些有趣的属性构造函数。但是当我对.NET不太熟悉时,由于属性被烘焙到程序集元数据中,它们不可能在程序运行时更改(但事实证明它们可以更改)。所以这样的构造器肯定会给人一个可怕的惊喜。
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
[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;
    }
}