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

时间:2010-12-20 12:47:38

标签: c# .net static-constructor typeinitializer

  

可能重复:
  How do I invoke a static constructor with reflection?

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

我试过了:

fooType.TypeInitializer.Invoke (new object[0]);

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

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

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

2 个答案:

答案 0 :(得分:8)

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

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

    static Statics1()
    {
        Console.WriteLine("Statics1 cctor");
        Value1 = "Initialized 1";
    }
}

代码:

Type staticType = typeof (Statics1);
staticType.TypeInitializer.Invoke(null);
or
staticType.TypeInitializer.Invoke(new object[0]);

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

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

Type staticType = typeof (Statics1);
staticType.TypeInitializer.Invoke(null, null);

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


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

Console.WriteLine(Statics1.Value1);

Type staticType = typeof (Statics1);
staticType.TypeInitializer.Invoke(null, null);

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

此外,尽管我更喜欢静态构造函数,但从性能的角度来看,字段初始值设定项比静态构造函数<{3}}

答案 1 :(得分:0)

编辑:显然不会按原样运作,因为海报状态无法提前知道类型。离开这里可能有助于澄清未来的读者...

如果我理解你的需求 - 在类似的情况下,我创建一个引用静态类的包装器,但仍然是测试套件的一部分。然后,您可以实例化包装器并按需初始化静态。这意味着您可以保持架构不变,并将包装器作为测试框架的一部分。

public static class MyStatic
{
    public static string SomeToolMethod()
    {
        return "Hello";
    }
}

public class MyStaticWrapper // or proxy, technically?
{
    public static string SomeToolMethod()
    {
        return MyStatic.SomeToolMethod();
    }
}

fooType.TypeInitializer.Invoke(new MyStaticWrapper()); /// untested, not sure of syntax here