【问题标题】:How do I invoke a static constructor with reflection?如何使用反射调用静态构造函数?
【发布时间】:2010-03-26 16:29:14
【问题描述】:

如何获取静态构造函数的ConstructorInfo

public class MyClass
{
    public static int SomeValue;

    static MyClass()
    {
        SomeValue = 23;
    }
}

我尝试了以下方法,但失败了......

 Type myClass = typeof (MyClass);

 // throws exception
 myClass.TypeInitializer.Invoke(null);    

 // returns null (also tried deleting  BindingFlags.Public
 ConstructorInfo ci = myClass.GetConstructor(BindingFlags.Static|BindingFlags.Public, System.Type.DefaultBinder, System.Type.EmptyTypes, null);

 // returns empty array
 ConstructorInfo[] clutchingAtStraws = myClass.GetConstructors(BindingFlags.Static| BindingFlags.Public);

【问题讨论】:

    标签: c# reflection


    【解决方案1】:

    还有System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(RuntimeTypeHandle type),额外保证静态构造函数只调用一次,不管方法调用多少次:

    Type myClass = typeof(MyClass);
    System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(myClass.TypeHandle);
    

    Reference

    【讨论】:

      【解决方案2】:

      使用myClass.TypeInitializer.Invoke(null, null)

      我刚刚尝试过,效果很好。

      我强烈建议您不要这样做,但是 - 它违反了期望静态构造函数只执行一次的类型。如果您只是想确保初始化一个类,请按照Oliver's answer 使用RuntimeHelpers.RunClassConstructor

      【讨论】:

      • 我需要按顺序访问它to apply an aspect to it using PostSharp。我想这仍然是一个有效的用例。
      • 投反对票,只是因为下一个答案(至少在理论上)更安全。 p.s. ...该死的,我只是对 Jon Skeet 的回答投了反对票。我是不是很大胆?
      • @AndriyK:添加了指向 RunClassConstructor 的链接,并感谢 Oliver 的回答。
      【解决方案3】:

      尽管有可能,但这样做可能不是一个好主意。但是,如果您访问该类的任何成员,运行时将自动为您调用静态构造函数。例如:

      // Read the field 'SomeValue', so that the runtime invokes static ctor   
      Type myClass = typeof(MyClass);
      myClass.GetField("SomeValue").GetValue(null);
      

      由于访问类的字段不会导致任何副作用(除了初始化类和调用静态构造函数),这通常应该是一种相对安全的方法(但是,它仍然可以工作仅适用于具有一些静态字段的类)。这样做的好处是它保证类型构造函数将被调用最多一次,这非常重要。

      【讨论】:

      • 很奇怪,但我提出这个问题只是因为我需要的只读字段在我访问它时没有启动。我敢打赌,大多数人都出于同样的原因来到这里。
      • 不,它没有。这就是我来这里的原因。 @Andriy_K +1
      【解决方案4】:

      您是否也尝试过 BindingFlags.Private?

      注意,静态构造函数保证在调用这个类的任何其他实例或静态方法之前被调用,并且保证是线程安全的并且只被调用一次。

      如果你用反射明确地调用它,你可能会造成很多伤害..

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-01-11
        • 1970-01-01
        相关资源
        最近更新 更多