Comment initialiser une classe statique C # avant qu’elle ne soit réellement nécessaire?

J’ai une classe statique avec un constructeur statique qui prend un certain temps (10-15 secondes) pour exécuter et initialiser complètement la classe. Afin d’améliorer les performances, j’ai décidé d’activer explicitement l’initialisation de cette classe statique au lieu de la première fois, afin qu’elle soit prête à l’emploi lorsqu’elle doit réellement être utilisée.

Ma première pensée a été de créer une méthode Initialize() pour la classe, mais comme j’ai déjà un constructeur statique, cette méthode ne semble pas avoir besoin de faire autre chose que d’être la méthode à appeler pour initialiser explicitement la classe sans accéder à aucun de ses autres méthodes ou propriétés publiques. Avoir une méthode qui ne fait rien directement ne me semble pas juste.

Ensuite, j’ai pensé que je pouvais simplement déplacer le code du constructeur statique dans cette méthode Initialize() , mais j’aimerais également que la classe soit initialisée lorsqu’elle est nécessaire pour la première fois et que la méthode Initialize() n’est pas explicitement appelée.

Pour résumer, je souhaite que les critères suivants soient observés:

  • Je veux permettre à la classe statique d’être explicitement initialisée (probablement en utilisant une méthode publique Initialize() ).
  • Je ne souhaite pas avoir à accéder à d’autres méthodes ou propriétés publiques de la classe lorsque je n’en ai pas besoin, même si cela initialiserait la classe statique.
  • Si la classe n’a pas été explicitement initialisée, je souhaite tout de même l’initialiser dès qu’elle est nécessaire (par exemple, lors de l’access à d’autres méthodes ou propriétés publiques dans le but d’utiliser les fonctionnalités ou les données fournies).
  • Il s’agit d’une classe d’assistance et l’utilisation du modèle de conception Singleton n’est pas nécessaire pour mes besoins.

Quelle serait la bonne façon de respecter les critères ci-dessus pour une classe statique écrite en C #? Cela peut également s’appliquer à d’autres langages de programmation (par exemple, Java), mais une solution écrite en C # m’intéresse personnellement.

J’irais probablement juste pour la méthode Initialize – et cela peut faire quelque chose d’intéressant

  • Il peut enregistrer que vous essayez explicitement d’initialiser la classe, avec une trace de stack
  • Une exception peut être levée si la classe est déjà initialisée via un autre appel Initialize .
  • Vous pouvez éventuellement (avec un peu d’effort et de réorganisation) sortinger les choses de sorte que toutes les exceptions causées lors de l’initialisation soient propagées sans l’ TypeInitializationException que vous auriez normalement.

J’irais avec la méthode d’initialisation (EDIT: voir la réponse de Jon). Mais si vous voulez vraiment utiliser le constructeur, vous pouvez le faire:

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

RunClassConstructor vous permet de forcer le constructeur de classe (constructeur statique) à s’exécuter s’il ne l’a pas déjà fait. S’il a déjà été exécuté, par exemple, parce que vous avez utilisé un membre statique de la classe, cela n’a aucun effet. L’exécution de fois supplémentaires n’a aucun effet.

Je ne sais pas si vous pouvez spécifier quand un constructeur statique est chargé.

De MSDN “Un constructeur statique est appelé automatiquement pour initialiser la classe avant la création de la première instance ou la référence de tous les membres statiques.”

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

* EDIT: * L’ ajout du motif singleton aiderait-il ici? Le getter peut appeler Initialize () en cochant un indicateur dans la classe, IsLoaded = true. Les appels suivants n’appelleront pas Initialize ()

Deux solutions de contournement:

  1. Déplacez le code constructeur à Initialize() pour pouvoir appeler explicitement. Et remplacez le code dans le constructeur pour appeler simplement la méthode Initialize() au cas où la classe statique serait chargée dynamicment avant que vous ne l’appeliez explicitement

     public static class StaticClass { // actual constructor static StaticClass() { Initialize(); } // explicit "constructor" public static void Initialize() { MyProperty = "Some Value"; } public static ssortingng MyProperty { get; set; } } 

    Puis initialisez comme ceci si vous voulez:

     StaticClass.Initialize(); 

    Ou il sera initialisé dynamicment la première fois qu’il est utilisé

  2. Pas aussi sémantiquement vierge, mais vous pouvez déclencher l’initialisation organique d’une classe statique en consommant simplement une propriété et en la lançant dans une variable temporaire.

    Alors faites ceci:

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

    Vous permet toujours de l’appeler à tout moment, mais s’il y a un coût de performances lors de l’initialisation, vous pouvez essayer de l’invoquer au démarrage, plutôt que la première fois que l’utilisateur fait quelque chose qui déclenche ce code.

Pour un autre aperçu utile de l’initialisation statique, voir: L’ordre d’initialisation de la classe statique en C # est-il déterministe?

L’approche ne me semble pas dégoûtante. Je pourrais nommer la méthode Touch (), lui donner un corps vide et append un commentaire approprié. Cela suffirait-il pour vous convaincre que quelque chose ne va pas?