J'ai plusieurs instances de formulaires dans mon application de formulaire Windows que j'instancie lors du chargement du formulaire principal (y compris une instance du formulaire principal lui-même). Je voudrais qu'ils soient partagés entre les classes afin que je puisse les utiliser depuis n'importe quel endroit. Je dois également utiliser les membres de chaque classe à travers ces instances.
Veuillez noter que je suis très confus quant à la façon dont cela fonctionne. Je ne sais pas comment je devrais déclarer des instances de mes formulaires mais je ne veux qu'une seule instance de chacun afin de pouvoir utiliser la méthode .Hide () et aussi utiliser les membres de chaque formulaire / classe.
I 'ai essayé de faire des instances en tant que propriétés mais je ne sais pas comment procéder. Je ne suis pas sûr que ce soit correct.
// get and set for form instances
public Menu menu { get; set; }
public RandomFacts randomFacts { get; set; }
public QuizMenu qm { get; set; }
public AskHowManyQuestions ahmq { get; set; }
// in the main form load method
menu = new Menu();
randomFacts = new RandomFacts();
qm = new QuizMenu();
ahmq = new AskHowManyQuestions();
Ce code se trouve dans la même forme «principale».
J'espère que vous pourrez m'aider en étant capable d'accéder à ces instances dans le monde entier et de m'aider à résoudre ce problème. Merci d'avoir lu mon problème.
3 Réponses :
Exemple trivial:
Singleton.GetSingleton();
Vous pouvez accéder à cette intance en faisant
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
var NewClassInstance = Singleton.GetSingleton().NewClassInstance;
Singleton.GetSingleton().NewClassInstance.Method();
var OtherClassInstance = Singleton.GetSingleton().OtherClassInstance;
var Proparty = OtherClassInstance.Name;
}
}
public class Singleton
{
public NewClass NewClassInstance {get; private set;}
public OtherClass OtherClassInstance {get; private set;}
private static readonly NewClass _newClass = new NewClass();
private static readonly OtherClass _otherClass = new OtherClass();
private static readonly Singleton _singleton = new Singleton();
private Singleton()
{
NewClassInstance = _newClass;
OtherClassInstance = _otherClass;
// Prevent outside instantiation
}
public static Singleton GetSingleton()
{
return _singleton;
}
}
public class NewClass
{
public NewClass()
{
}
public void Method()
{
}
}
public class OtherClass
{
public string Name {get; set;}
public OtherClass()
{
}
}
Laissez-vous un autre exemple https://dotnetfiddle.net/C1PB05
Alors, est-ce que je fais cela pour chaque formulaire dans mon cas? Merci pour l'explication.
De cette façon, vous pouvez créer une instance de chaque classe une seule fois et y accéder à tout moment sans créer une nouvelle instance dans votre cause, vous pouvez le faire pour n'importe quelle classe que vous souhaitez partager
Je vous remercie. Dans mon cas, est-ce que je change chaque constructeur de formulaire public en un constructeur privé? Et définissez simplement les propriétés sous l'appel à InitializeComponent (); , répéter ce processus pour chaque classe? Désolé, je suis juste confus. @AmadeuAntunes
Le motif singleton est mignon, mais je ne suis pas vraiment convaincu que ce soit le bon endroit pour cela. Peut-être ... mais ça sent le poisson. Je recommanderais l'approche où les instances sont passées dans les deux sens par les constructeurs.
Votre singleton de classe doit avoir accès à d'autres classes pour pouvoir l'instancier
@ Vilx - C'est un moyen simple de partager des instances
@AmadeuAntunes Oui, mais cela vous limite également à une instance par formulaire. Si un jour vous souhaitez instancier deux copies du même formulaire (pour une raison quelconque), les choses vont devenir laides.
@vous pouvez toujours dupliquer des instances dans la classe singleton
Les singletons sont généralement utilisés pour des choses qui sont singulières par leur nature même. Quelque chose où il est absolument inconcevable que vous ayez jamais besoin d'une autre instance. En fait, 90% de ces cas sont encore mieux résolus avec des classes / propriétés statiques. Les singletons sont pour le cas où vous avez absolument besoin que ce soit une instance, mais vous avez également besoin d'avoir une seule instance. Comme DBNull , c'est un bon exemple.
Dans ce cas, nous avons besoin qu'il s'agisse d'une instance (les formulaires ne peuvent pas être statiques), mais il n'est pas vraiment nécessaire de nous limiter à une seule instance. Nous n'avons simplement pas besoin d'une autre instance pour le moment, donc un singleton fonctionne, mais cela ne semble pas être la bonne solution.
Pardonnez-moi mais je ne suis toujours pas sûr. Dois-je créer une nouvelle classe pour servir de «Singleton»?
Dans cet exemple oui
Donc, chaque fois que j'ai besoin d'utiliser l'instance unique, peu importe où je me trouve, je tape simplement "var NewClassInstance = Singleton.GetSingleton (). NewClassInstance;"?
oui, vous pouvez appeler n'importe où le singleton pour obtenir les autres instances
Maintenant, j'obtiens: System.TypeInitializationException: «L'initialiseur de type pour« wQuiz.Single »a levé une exception.». C'est à ce moment que j'essaye de faire le code: var MenuForm = Single.GetSingle (). MenuForm;
Attribuez-les simplement aux propriétés de vos formulaires
public SharedState SharedState { get; set; }
De toute évidence, vos formulaires doivent déclarer une propriété SharedState :
// in the main form load method
// Class which holds all of the state shared by these forms
sharedState = new SharedState();
menu = new Menu() { SharedState = sharedState };
randomFacts = new RandomFacts() { SharedState = sharedState };
ahmq = new AskHowManyQuestions() { SharedState = sharedState };
qm = new QuizMenu() { SharedState = sharedState };
Une chose à noter, si vous ne conservez pas un constructeur sans paramètre pour le formulaire en plus du constructeur qui prend dans SharedState, le concepteur visuel du formulaire peut ne pas fonctionner.
@ScottChamberlain fair point - modifié pour utiliser les propriétés à la place, ce qui sera plus facile à grok
@ScottChamberlain J'avais peur de ça aussi, mais curieusement, je n'ai jamais eu de problème avec ça. J'ai créé des formulaires avec un seul constructeur privé et des formulaires avec un seul constructeur paramétré et le concepteur ne s'est pas plaint une seule fois. Je soupçonne qu'il ne les instancie pas réellement, il analyse simplement la méthode InitComponents .
@ Vilx- J'ai peut-être pensé à des contrôles personnalisés au lieu d'un formulaire. Je crois que si vous créez un contrôle personnalisé et que vous le faites lorsque vous essayez de l'ajouter dans le concepteur sur un formulaire, cela gâche.
@ScottChamberlain - Maintenant que vous en parlez ... c'est peut-être moi qui ai fait des contrôles personnalisés et cela a fonctionné? C'était il y a longtemps, et je ne me souviens plus vraiment ... Quoi qu'il en soit, je suppose que la morale est - cela pourrait échouer, voyez par vous-même si cela fonctionne dans votre cas.
Je ne veux qu'une seule instance de chaque
Déplacez vos déclarations dans leur propre classe et implémentez le modèle Singleton. Étant donné que vous utilisez des formulaires, vous pouvez les instancier à la demande et les remettre à zéro lorsqu'ils sont fermés en vous abonnant à leur événement FormClosed.
Exemple d'utilisation:
class MyForms { private static Menu _menu = null; public static Menu menu { get { if (_menu == null || _menu.IsDisposed) { _menu = new Menu(); _menu.FormClosed += (sender, e) => { _menu = null; }; } return _menu; } } private static RandomFacts _randomFacts = null; public static Menu randomFacts { get { if (_randomFacts == null || _randomFacts.IsDisposed) { _randomFacts = new RandomFacts(); _randomFacts.FormClosed += (sender, e) => { _randomFacts = null; }; } return _menu; } } private static QuizMenu _qm = null; public static QuizMenu qm { get { if (_qm == null || _qm.IsDisposed) { _qm = new QuizMenu(); _qm.FormClosed += (sender, e) => { _qm = null; }; } return _qm; } } private static AskHowManyQuestions _ahmq = null; public static AskHowManyQuestions ahmq { get { if (_ahmq == null || _ahmq.IsDisposed) { _ahmq = new AskHowManyQuestions(); _ahmq.FormClosed += (sender, e) => { _ahmq = null; }; } return _ahmq; } } }
Vérifiez ceci: stackoverflow.com/a/53658779/5718868
Il convient de noter que le modèle d'utilisation de Singleton est déconseillé en faveur de l'injection de dépendances explicite dans les constructeurs.
D'accord avec @theMayer uniquement avec l'avertissement que les deux choses ne sont pas mutuellement exclusives - vous devez toujours utiliser des instances singleton dans des cas comme celui-ci, vous ne devriez tout simplement pas laisser votre code dépendant contrôler la durée de vie de ses dépendances. C'est un travail pour la racine de la composition.
Copie possible de C # Permettre le partage de plusieurs classes la même instance d'une autre classe