如何在实际需要之前初始化C#静态类?
我有一个带静态构造函数的静态类,需要一些时间(10-15秒)来执行并完全初始化类。 为了提高性能,我决定将这个静态类显式初始化,而不是在第一次需要它时,以便在实际需要使用时准备好。
我的第一个想法是为类创建一个Initialize()
方法,但由于我已经有了一个静态构造函数,这个方法除了是调用显式初始化类而不访问任何类的方法之外似乎不需要做任何其他事情。其他公共方法或财产。 拥有一种不直接做任何事情的方法对我来说似乎并不合适。
然后我想我可以将代码从静态构造函数移动到这个Initialize()
方法中,但是我还希望在首次需要时初始化类并且没有显式调用Initialize()
方法。
总而言之,我希望遵守以下标准:
- 我想允许显式初始化静态类(可能通过使用公共
Initialize()
方法)。 - 我不想在不需要它时访问类上的任何其他公共方法或属性,即使这会初始化静态类。
- 如果该类尚未显式初始化,我仍然希望在首次需要时初始化它(即访问其他公共方法或属性时,意图使用它们提供的function或数据)。
- 这是一个帮助类,使用Singleton设计模式对我的目的来说不是必需的。
对于用C#编写的静态类,遵循上述标准的正确方法是什么? 这也适用于其他编程语言(例如Java),但我个人对使用C#编写的解决方案感兴趣。
我可能只是去寻找Initialize
方法 – 它可以做一些有用的事情:
- 它可以记录您明确尝试使用堆栈跟踪初始化类
- 如果已经通过另一个
Initialize
调用初始化了类,则可能会抛出exception - 您可能 (通过一些努力和重组)对事物进行排序,以便在初始化期间导致的任何exception都会在没有您通常获得的
TypeInitializationException
情况下传播。
我会选择初始化方法(编辑:请参阅Jon的回答)。 但是如果你真的只想使用构造函数,你可以这样做:
var type = typeof (YourType); System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(type.TypeHandle);
RunClassConstructor
允许您强制类构造函数(静态构造函数)运行(如果它尚未运行)。 如果它已经运行,比如因为你使用了类的静态成员,那么这没有效果。 再运行一次没有效果。
我不确定你是否可以指定何时加载静态构造函数。
从MSDN“在创建第一个实例或引用任何静态成员之前,会自动调用静态构造函数来初始化类。”
http://msdn.microsoft.com/en-us/library/k9x6w0hc(v=vs.80).aspx
* 编辑:*添加单身模式会有帮助吗? getter可以通过检查类中的标志IsLoaded = true来调用Initialize()。 后续调用不会调用Initialize()
两种解决方法:
-
将构造函数代码移动到
Initialize()
以便可以显式调用。 并且在构造函数内部的代码替换为只调用Initialize()
方法,以防静态类在您明确调用之前动态加载public static class StaticClass { // actual constructor static StaticClass() { Initialize(); } // explicit "constructor" public static void Initialize() { MyProperty = "Some Value"; } public static string MyProperty { get; set; } }
如果你想要,那么初始化如下:
StaticClass.Initialize();
或者它会在第一次使用时动态初始化
-
不像语义上原始,但您可以通过使用属性并将其抛入临时变量来触发静态类的有机初始化。
所以这样做:
// trigger static initilaization var dummy = StaticClass.MyProperty;
仍然允许您在需要时调用它,但如果初始化时有一些性能成本,您可以尝试在启动时调用它,而不是在用户第一次执行触发该代码的操作时调用它。
有关静态初始化的另一个有用的概述,请参阅: C#中的静态类初始化的顺序是否确定?
这种方法对我来说似乎并不好看。 我可能会将方法命名为Touch(),给它一个空体,并添加适当的注释。 这足以让你感觉到某种事情对此感觉不对劲吗?