如何显式运行未知类型的静态构造函数?

maf*_*afu 7 .net c# static-constructor typeinitializer

可能重复:
如何使用反射调用静态构造函数?

我在各种类的静态构造函数中有一些初始化代码.我不能创建实例,也不提前知道类型.我想确保加载类.

我试过这个:

fooType.TypeInitializer.Invoke (new object[0]);
Run Code Online (Sandbox Code Playgroud)

但得到一个MemberAccessException:类型初始化程序不可调用.

我假设这是因为cctor是私有的?有没有办法在不改变架构的情况下解决这个问题?

编辑:我找到了一个解决方法使用RuntimeHelpers.RunClassConstructor,但这种方式似乎几乎没有在MSDN中记录,我不确定它是一个黑客或一个合理的,prod系统的方式.

SWe*_*eko 8

我不确定为什么会这样,但据我所知(在Skeet的帮助下),如果我有一个静态类

public static class Statics1
{
    public static string Value1 { get; set; }

    static Statics1()
    {
        Console.WriteLine("Statics1 cctor");
        Value1 = "Initialized 1";
    }
}
Run Code Online (Sandbox Code Playgroud)

代码:

Type staticType = typeof (Statics1);
staticType.TypeInitializer.Invoke(null);
or
staticType.TypeInitializer.Invoke(new object[0]);
Run Code Online (Sandbox Code Playgroud)

将抛出异常,因为不知何故这会解析为.ctor,而不是类的.cctor.
如果我使用一个显式静态类,它被视为一个抽象的密封类,所以例外是一个抽象类无法实例化,如果我使用一个静态构造函数的常规类,例外的是类型初始值设定项不是调用.

但是如果我使用带有两个参数的Invoke重载(实例,参数),就像这样:

Type staticType = typeof (Statics1);
staticType.TypeInitializer.Invoke(null, null);
Run Code Online (Sandbox Code Playgroud)

显式地声明我正在调用静态方法(这是第一个null的意思 - 没有实例==静态),这可以工作并初始化类.


也就是说,静态构造函数是奇怪的野兽.以这种方式调用一个将调用静态构造函数,即使它已经被执行,即此代码:

Console.WriteLine(Statics1.Value1);

Type staticType = typeof (Statics1);
staticType.TypeInitializer.Invoke(null, null);
Run Code Online (Sandbox Code Playgroud)

将两次调用静态构造函数.因此,如果您的cctors具有潜在的重要副作用,例如创建文件,打开数据库等,您可能需要重新考虑这种方法.

此外,尽管出于可读性的原因我更喜欢静态构造函数,但从性能角度来看,字段初始化程序比静态构造函数一点.