Pergunta

Como faço para implementar o padrão singleton em C #? Eu quero colocar minhas constantes e algumas funções básicas nele como eu usar aqueles em todos os lugares no meu projeto. Eu quero tê-los 'global' e não precisa manualmente aprisioná-los cada objeto que eu criar.

Foi útil?

Solução

Se você está apenas armazenar alguns valores globais e têm alguns métodos que não precisam de estado, você não precisa de Singleton. Basta fazer a classe e suas propriedades / métodos estático.

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

   public static string MangleString( string someValue )
   {
   }
}

Singleton é mais útil quando você tem uma classe normal com estado, mas somente a um deles. Os links que outros tenham prestado deve ser útil para explorar o padrão Singleton.

Outras dicas

Singleton != Global. Você parece estar procurando a palavra-chave static.

Singletons só fazem sentido se ambos destas condições:

  1. O objeto deve ser Global
  2. Não deve somente sempre existe um única instância do objeto

Note que # 2 não significa que você como o objeto para ter apenas uma única instância - se isso é o caso, basta instanciar apenas uma vez - isso significa que há must (como, é perigoso para que isso não seja verdade) sempre apenas ser uma única instância.

Se você quiser global, basta fazer uma instância global de alguns (não signleton) objeto (ou torná-lo estático ou qualquer outro). Se você quiser apenas uma instância, mais uma vez, estático é seu amigo. Além disso, simplesmente instanciar apenas um objeto.

Isso é minha opinião de qualquer maneira.

Você pode realmente simplificar a implementação singleton, este é o que eu uso:

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

    private static readonly FooService _instance = new FooService();

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

Hmm, tudo isso parece um pouco complexo.

Por que você precisa de um quadro de injeção de dependência para obter um singleton? Usando um recipiente COI é bom para algum aplicativo empresarial, (contanto que não é usado em demasia, é claro), mas, ah, o cara só quer saber aboiut implementar o padrão.

Por que nem sempre ansiosamente instanciar, em seguida, fornecer um método que retorna a estática, a maior parte do código escrito acima, então vai embora. Siga o velho ditado C2 - DoTheSimplestThingThatCouldPossiblyWork ...

Eu recomendo que você leia o artigo Explorando o Design Pattern Singleton disponível no MSDN. Ele detalha as características do quadro que tornar o padrão simples de implementar.

Como um aparte, eu confira a leitura relacionada no SO sobre Singletons .

Ignorando a questão de saber se você deve ou não estar usando o padrão Singleton, que tem sido discutido em outro lugar, eu iria implementar um singleton como esta:

/// <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() {

    }

}

estática Singleton é praticamente um anti padrão, se você quer um projeto de baixo acoplamento. Evite, se possível, ea menos que este é um sistema muito simples que eu recomendo ter um olhar para um dos muitos frameworks de injeção de dependência disponíveis, tais como http://ninject.org/ ou http://code.google.com / p / Autofac / .

Para se inscrever / consumir um tipo configurado como um singleton em Autofac você faria algo como o seguinte:

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>();

A resposta aceita é uma solução terrível pela forma, pelo menos verificar as rachaduras que realmente implementadas o padrão.

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); }
    }

}

Eu gosto deste teste padrão, apesar de não impedir alguém de criar uma instância não-singleton. Ele pode, por vezes, pode ser melhor para educar os desenvolvedores de sua equipe sobre o uso da metodologia de direita versus indo para comprimentos heróicos para evitar algum idiota de usar seu código de forma errada ...

    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();

Isto lhe dará uma única instância (instanciado o caminho certo) e vai efetivamente ser preguiçoso, porque o construtor estático não obter chamado até Construir () é chamado.

O que você está descrevendo é meramente funções e constantes estáticas, não um singleton. O padrão de design Singleton (que é muito raramente necessário) descreve uma classe que é instanciado, mas apenas uma vez, automaticamente, quando usado pela primeira vez.

Ele combina a inicialização lenta com um cheque para evitar múltipla instanciação. É apenas realmente útil para as classes que envolvem algum conceito que está fisicamente singular, como um invólucro em torno de um dispositivo de hardware.

constantes e funções estáticas são apenas isso: um código que não precisa de uma instância de todo

.

Pergunte a si mesmo: "Será que esta pausa classe se houver mais de uma instância do mesmo" Se a resposta é não, você não precisa de um singleton.

hmmm ... Poucos constantes com funções relacionadas ... que não iria mais ser alcançado através de enums? Eu sei que você pode criar um enum personalizado em Java com os métodos e todos, o mesmo deve ser atingível em C #, se não for suportado diretamente, em seguida, pode ser feito com singleton classe simples com construtor privado.

Se suas constantes são semanticamente relacionados que você deve considerar enums (ou conceito equivalente) você vai ganhar todas as vantagens das variáveis ??const estáticas + você será capaz de usar a sua vantagem a verificação de tipo do compilador.

O meu 2 cêntimos

Pessoalmente eu gostaria de ir para um quadro de injeção de dependência, como Unidade, todos eles são capazes de configurar Singleton itens no recipiente e melhoraria o acoplamento ao passar de uma dependência de classe para dependência interface.

Ao esconder construtor público, adicionando um campo estático privado para manter este único exemplo, e adicionando um método de fábrica estático (com inicializador preguiçoso) para retornar que única instância

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();
    }   
}

Eu escrevi uma classe para o meu projeto usando o padrão Singleton. É muito fácil de usar. Espero que ele vai trabalhar para você. Por favor, encontrar o seguinte código.

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;
    }
}
}

Agora você pode definir o valor da variável para o código acima em seu pedido como este ..

[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");
}

E você pode recuperar esses valores como esta ..

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();
    }

Em c # poderia ser (segmento seguro, bem como a inicialização lenta):

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());
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top