我在各种类的静态构造函数中有一些初始化代码。我不能创建实例,也不提前知道类型。我想确保加载类。
我试过了:
fooType.TypeInitializer.Invoke (new object[0]);
但是得到了一个MemberAccessException:类型初始化程序不可调用。
我假设这是因为cctor是私有的?有没有办法在不改变架构的情况下解决这个问题?
编辑:我找到了一个使用RuntimeHelpers.RunClassConstructor
的解决方法,但这种方式似乎在MSDN中几乎没有记录,我不确定它是一个黑客还是一个合理的,生产系统的方式。
答案 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