简体   繁体   English

如何在实际需要之前初始化C#静态类?

[英]How to initialize a C# static class before it is actually needed?

I have a static class with a static constructor that takes some time (10-15 seconds) to execute and fully initialize the class. 我有一个带有静态构造函数的静态类,需要花费一些时间(10-15秒)来执行并完全初始化类。 In order to improve performance, I've decided to enable this static class to be explicitly initialized instead of when it is first needed so that it is ready to go when it actually needs to be used. 为了提高性能,我决定将这个静态类显式初始化,而不是在第一次需要它时,以便在实际需要使用时准备好。

My first thought was to create an Initialize() method for the class, but since I already have a static constructor, this method doesn't seem to need to do anything other than be the method to call to explicitly initialize the class without accessing any of its other public methods or properties. 我的第一个想法是为类创建一个Initialize()方法,但由于我已经有了一个静态构造函数,这个方法似乎不需要做任何事情,除了是调用显式初始化类而不访问任何类的方法其他公共方法或财产。 Having a method that does nothing directly doesn't seem right to me. 拥有一种不直接做任何事情的方法对我来说似乎并不合适。

Then I thought I can just move the code from the static constructor into this Initialize() method, but I'd also like the class to be initialized when it is first needed and the Initialize() method wasn't explicitly called. 然后我想我可以将代码从静态构造函数移动到这个Initialize()方法中,但是我还希望在首次需要时初始化类并且没有显式调用Initialize()方法。

To summarize, I want the following criteria to be observed: 总而言之,我希望遵守以下标准:

  • I want to allow the static class to be explicitly initialized (likely by using a public Initialize() method). 我想允许显式初始化静态类(可能通过使用公共Initialize()方法)。
  • I don't want to have to access any other public methods or properties on the class when I don't need them, even though this would initialize the static class. 我不想在不需要它时访问类上的任何其他公共方法或属性,即使这会初始化静态类。
  • If the class has not been explicitly initialized, I still want to initialize it when it is first needed (ie when accessing other public methods or properties with the intent of using the functionality or data they provide). 如果该类尚未显式初始化,我仍然希望在首次需要时初始化它(即访问其他公共方法或属性时,意图使用它们提供的功能或数据)。
  • This is a helper class and using the Singleton design pattern is not necessary for my purposes. 这是一个帮助类,使用Singleton设计模式对我来说不是必需的。

What would be the proper way to observe the above criteria for a static class written in C#? 对于用C#编写的静态类,遵循上述标准的正确方法是什么? This can also apply to other programming languages (eg Java), but I'm personally interested in a solution written in C#. 这也适用于其他编程语言(例如Java),但我个人对使用C#编写的解决方案感兴趣。

I would go with the initialize method (EDIT: See Jon's answer). 我会使用初始化方法(编辑:请参阅Jon的答案)。 But if you really just want to use the constructor, you can do this: 但是如果你真的只想使用构造函数,你可以这样做:

var type = typeof (YourType);
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(type.TypeHandle);

RunClassConstructor allows you to force the class constructor (static constructor) to run if it already hasn't. RunClassConstructor允许您强制类构造函数(静态构造函数)运行(如果它尚未运行)。 If it has already run, say because you used a static member of the class, then this has no effect. 如果它已经运行,比如因为你使用了类的静态成员,那么这没有效果。 Running it additional times has no effect. 再运行一次没有效果。

I would probably just go for the Initialize method - and it can do something useful: 我可能只是去寻找Initialize方法 - 它可以做一些有用的事情:

  • It can log that you're explicitly trying to initialize the class, with a stack trace 它可以记录您明确尝​​试使用堆栈跟踪初始化类
  • It might throw an exception if the class is already initialized via another Initialize call 如果已经通过另一个Initialize调用初始化了类,则可能会抛出异常
  • You could possibly (with a bit of effort and reorganization) sort things so that any exceptions caused during initialization were propagated without the TypeInitializationException which you'd normally get. 可能 (通过一些努力和重组)对事物进行排序,以便在初始化期间导致的任何异常都会传播,而不会TypeInitializationException您通常会得到的TypeInitializationException

Two work-arounds: 两种解决方法:

  1. Move the constructor code to Initialize() so you can call explicitly. 将构造函数代码移动到Initialize()以便可以显式调用。 And replace the code inside the constructor to just call the Initialize() method in case the static class is loaded dynamically before you've called it explicitly 并且在构造函数内部的代码替换为只调用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; } } 

    Then initialize like this if you want: 如果你想要,那么初始化如下:

     StaticClass.Initialize(); 

    Or it will be dynamically initialized the first time it's used 或者它会在第一次使用时动态初始化

  2. Not as semantically pristine, but you can trigger the organic initialization of a static class just by consuming a property and throwing it in a temporary variable. 不像语义上那样原始,但是你可以通过使用属性并将其抛入临时变量来触发静态类的有机初始化。

    So just do this: 所以这样做:

     // trigger static initilaization var dummy = StaticClass.MyProperty; 

    Still allows you to call it whenever you need to, but if there is some performance cost on initialization, you can try to invoke it on startup, rather than the first time the user does something that fires that code. 仍然允许您在需要时调用它,但如果在初始化时有一些性能成本,您可以尝试在启动时调用它,而不是在用户第一次执行触发该代码的操作时。

For another helpful outline of static initialization see: Is the order of static class initialization in C# deterministic? 有关静态初始化的另一个有用的概述,请参阅: C#中静态类初始化的顺序是否确定?

I'm not sure if you can specify when a static constructor is loaded. 我不确定你是否可以指定何时加载静态构造函数。

From MSDN "A static constructor is called automatically to initialize the class before the first instance is created or any static members are referenced." 来自MSDN“在创建第一个实例或引用任何静态成员之前,会自动调用静态构造函数来初始化类。”

http://msdn.microsoft.com/en-us/library/k9x6w0hc(v=vs.80).aspx http://msdn.microsoft.com/en-us/library/k9x6w0hc(v=vs.80).aspx

* EDIT: * Would adding the singleton pattern help here? * 编辑:*添加单身模式会有帮助吗? The getter can call Initialize() by checking a flag in the class, IsLoaded=true. getter可以通过检查类中的标志IsLoaded = true来调用Initialize()。 Subsequent calls will not call Initialize() 后续调用不会调用Initialize()

The approach doesn't seem icky to me. 这种方法对我来说似乎并不好看。 I might name the method Touch(), give it an empty body, and add an appropriate comment. 我可能将方法命名为Touch(),给它一个空体,并添加适当的注释。 Would that be sufficient to get you over your feeling that something doesn't feel right about this? 这是否足以让你感觉到某些事情对此感觉不正确?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM