Question

Comment implémenter le motif singleton en C #? Je souhaite y mettre mes constantes et certaines fonctions de base, car je les utilise partout dans mon projet. Je veux les avoir 'globaux' et ne pas avoir besoin de les lier manuellement à chaque objet que je crée.

Était-ce utile?

La solution

Si vous ne stockez que des valeurs globales et que certaines méthodes n'ont pas besoin d'état, vous n'avez pas besoin de singleton. Il suffit de rendre la classe et ses propriétés / méthodes statiques.

public static class GlobalSomething
{
   public static int NumberOfSomething { get; set; }

   public static string MangleString( string someValue )
   {
   }
}

Singleton est le plus utile lorsque vous avez une classe normale avec un état, mais que vous n'en voulez qu'une. Les liens fournis par d’autres devraient être utiles pour explorer le modèle de Singleton.

Autres conseils

Singleton! = Global . Vous semblez rechercher le mot clé static .

Les singletons n'ont de sens que si les deux de ces conditions sont vraies:

  1. L'objet doit être global
  2. .
  3. Il ne doit exister qu'une instance unique de l'objet

Notez que # 2 ne signifie pas que vous aimeriez l’objet pour n’avoir qu’une seule instance - si tel est le cas, il suffit de l’instancier une fois - cela signifie que doit être (comme dans le cas, il est dangereux que cela ne soit pas vrai) ne soyez jamais qu'une seule instance.

Si vous voulez global, créez simplement une instance globale d’un objet (non signleton) (ou rendez-la statique ou autre). Si vous ne voulez qu'une instance, encore une fois, static est votre ami. De même, instanciez simplement un seul objet.

C’est mon avis quand même.

Vous pouvez vraiment simplifier une implémentation singleton, voici ce que j'utilise:

    internal FooService() { }        
    static FooService() { }

    private static readonly FooService _instance = new FooService();

    public static FooService Instance
    {
        get { return _instance; }
    }

Hmm, tout cela semble un peu complexe.

Pourquoi avez-vous besoin d’un framework d’injection de dépendance pour obtenir un singleton? Utiliser un conteneur IOC est acceptable pour certaines applications d'entreprise (tant qu'il n'est pas surutilisé bien sûr), mais, ah, le gars veut juste savoir avant de mettre en œuvre le modèle.

Pourquoi ne pas instancier toujours avec impatience, puis fournir une méthode qui retourne le statique, la plupart du code écrit ci-dessus disparaît ensuite. Suivez le vieil adage C2: DoTheSimplestThingThatChatCossPossiblyWork ...

Je vous recommanderais de lire l'article Explorer le modèle de conception Singleton disponible sur MSDN. Il détaille les fonctionnalités du framework qui rendent le modèle simple à implémenter.

En passant, je vérifierais les lectures associées sur les SO concernant les singletons .

Ignorant la question de savoir si vous devriez ou non utiliser le modèle Singleton, qui a été discuté ailleurs, je mettrais en œuvre un singleton comme ceci:

/// <summary>
/// Thread-safe singleton implementation
/// </summary>
public sealed class MySingleton {

    private static volatile MySingleton instance = null;
    private static object syncRoot = new object();

    /// <summary>
    /// The instance of the singleton
    /// safe for multithreading
    /// </summary>
    public static MySingleton Instance {
        get {
            // only create a new instance if one doesn't already exist.
            if (instance == null) {
                // use this lock to ensure that only one thread can access
                // this block of code at once.
                lock (syncRoot) {
                    if (instance == null) {
                        instance = new MySingleton();
                    }
                }
            }
            // return instance where it was just created or already existed.
            return instance;
        }
    }


    /// <summary>
    /// This constructor must be kept private
    /// only access the singleton through the static Instance property
    /// </summary>
    private MySingleton() {

    }

}

Le singleton statique est quasiment un anti-motif si vous voulez un design faiblement couplé. Évitez si possible, et à moins qu'il ne s'agisse d'un système très simple, je vous recommanderais de jeter un coup d'œil à l'un des nombreux frameworks d'injection de dépendance disponibles, tels que http://ninject.org/ ou http://code.google.com / p / autofac / .

Pour enregistrer / utiliser un type configuré en tant que singleton dans l'autofac, procédez comme suit:

var builder = new ContainerBuilder()
builder.Register(typeof(Dependency)).SingletonScoped()
builder.Register(c => new RequiresDependency(c.Resolve<Dependency>()))

var container = builder.Build();

var configured = container.Resolve<RequiresDependency>();

La réponse acceptée est une solution terrible en passant, au moins, vérifiez les responsables qui ont mis en œuvre le modèle.

public class Globals
{
    private string setting1;
    private string setting2;

    #region Singleton Pattern Implementation

    private class SingletonCreator
    {
        internal static readonly Globals uniqueInstance = new Globals();

        static SingletonCreator()
        {
        }
    }

    /// <summary>Private Constructor for Singleton Pattern Implementaion</summary>
    /// <remarks>can be used for initializing member variables</remarks>
    private Globals()
    {

    }

    /// <summary>Returns a reference to the unique instance of Globals class</summary>
    /// <remarks>used for getting a reference of Globals class</remarks>
    public static Globals GetInstance
    {
        get { return SingletonCreator.uniqueInstance; }
    }

    #endregion

    public string Setting1
    {
        get { return this.setting1; }
        set { this.setting1 = value; }
    }

    public string Setting2
    {
        get { return this.setting2; }
        set { this.setting2 = value; }
    }

    public static int Constant1 
    {
        get { reutrn 100; }
    }

    public static int Constat2
    {
        get { return 200; }
    }

    public static DateTime SqlMinDate
    {
        get { return new DateTime(1900, 1, 1, 0, 0, 0); }
    }

}

J'aime ce modèle, même s'il n'empêche personne de créer une instance non-singleton. Il peut parfois être préférable d’éduquer les développeurs de votre équipe sur l’utilisation de la bonne méthodologie plutôt que d’agir de façon héroïque afin d’empêcher certains knucklehead d’utiliser votre code de manière erronée ...

    public class GenericSingleton<T> where T : new()
    {
        private static T ms_StaticInstance = new T();

        public T Build()
        {
            return ms_StaticInstance;
        }
    }

...
    GenericSingleton<SimpleType> builder1 = new GenericSingleton<SimpleType>();
    SimpleType simple = builder1.Build();

Cela vous donnera une seule instance (instanciée de la bonne façon) et sera effectivement fainéant, car le constructeur statique ne sera pas appelé avant que Build () ne soit appelé.

Ce que vous décrivez n'est que des fonctions et des constantes statiques, pas un singleton. Le modèle de conception singleton (qui est très rarement nécessaire) décrit une classe qui est instanciée, mais une seule fois, automatiquement, lors de sa première utilisation.

Il combine une initialisation lente avec une vérification pour éviter les instanciations multiples. Ce n'est vraiment utile que pour les classes qui encapsulent un concept physiquement singulier, tel qu'un wrapper autour d'un périphérique matériel.

Les constantes et fonctions statiques ne sont que cela: un code qui n'a pas du tout besoin d'une instance.

Posez-vous la question suivante: "Cette classe sera-t-elle interrompue s’il ya plus d’une instance?" Si la réponse est non, vous n'avez pas besoin d'un singleton.

hmmm ... Peu de constantes avec des fonctions connexes ... ne serait-il pas préférable de le faire par des enums? Je sais que vous pouvez créer une énumération personnalisée en Java avec des méthodes. En principe, la même chose devrait être réalisable en C #. Si elle n'est pas directement prise en charge, elle peut être réalisée avec un simple singleton avec un constructeur privé.

Si vos constantes sont sémantiquement liées, vous devriez considérer des énumérations (ou un concept équivalent), vous obtiendrez tous les avantages des variables statiques const + vous pourrez utiliser à votre avantage la vérification de type du compilateur.

Mes 2 cent

Personnellement, je choisirais un framework d'injection de dépendances, comme Unity, tous capables de configurer des éléments singleton dans le conteneur et amélioreraient le couplage en passant d'une dépendance de classe à une dépendance d'interface.

En masquant le constructeur public, en ajoutant un champ statique privé pour contenir cette instance unique et en ajoutant une méthode de fabrique statique (avec initialisation différée) pour renvoyer cette instance unique

public class MySingleton   
{  
    private static MySingleton sngltn; 
    private static object locker;  
    private MySingleton() {}   // Hides parameterless ctor, inhibits use of new()   
    public static MySingleton GetMySingleton()       
    {     
        lock(locker)
            return sngltn?? new MySingleton();
    }   
}

J'ai écrit un cours pour mon projet en utilisant le modèle Singleton. C'est très facile à utiliser. J'espère que cela fonctionnera pour vous. Veuillez trouver le code suivant.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace TEClaim.Models
{
public class LogedinUserDetails
{
    public string UserID { get; set; }
    public string UserRole { get; set; }
    public string UserSupervisor { get; set; }
    public LogedinUserDetails()
    {

    }

    public static LogedinUserDetails Singleton()
    {
        LogedinUserDetails oSingleton;

        if (null == System.Web.HttpContext.Current.Session["LogedinUserDetails"])
        {               
            oSingleton = new LogedinUserDetails();
            System.Web.HttpContext.Current.Session["LogedinUserDetails"] = oSingleton;
        }
        else
        {              
            oSingleton = (LogedinUserDetails)System.Web.HttpContext.Current.Session["LogedinUserDetails"];
        }

        //Return the single instance of this class that was stored in the session
        return oSingleton;
    }
}
}

Vous pouvez maintenant définir la valeur de la variable pour le code ci-dessus dans votre application, comme ceci.

[HttpPost]
public ActionResult Login(FormCollection collection)
{
  LogedinUserDetails User_Details = LogedinUserDetails.Singleton();
  User_Details.UserID = "12";
  User_Details.UserRole = "SuperAdmin";
  User_Details.UserSupervisor = "815978";
  return RedirectToAction("Dashboard", "Home");
}

Et vous pouvez récupérer ces valeurs comme ceci.

public ActionResult Dashboard()
    {
        LogedinUserDetails User_Details = LogedinUserDetails.Singleton();
        ViewData["UserID"] = User_Details.UserID;
        ViewData["UserRole"] = User_Details.UserRole;
        ViewData["UserSupervisor"] = User_Details.UserSupervisor;

        return View();
    }

En c #, il pourrait s'agir de (thread sécurisé et initialisation lente):

public sealed class MySingleton
{
    static volatile Lazy<MySingleton> _instance = new Lazy<MySingleton>(() => new MySingleton(), true);
    public static MySingleton Instance => _instance.Value;
    private MySingleton() { }
}
public class Singleton
{
   private static Singleton _instance;
   public static Singleton Instance => _instance ?? (_instance = new Singleton());
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top