Как реализовать синглтон в С#?

Как реализовать шаблон singleton в С#? Я хочу поместить в него свои константы и некоторые основные функции, поскольку я использую их везде в своем проекте. Я хочу иметь их "Глобальный" и не нужно вручную привязывать их к каждому объекту, который я создаю.

Ответ 1

Если вы просто сохраняете некоторые глобальные значения и имеете некоторые методы, которые не нуждаются в состоянии, вам не нужен синглтон. Просто сделайте класс и его свойства/методы статичными.

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

   public static string MangleString( string someValue )
   {
   }
}

Синглтон наиболее полезен, если у вас нормальный класс с состоянием, но вам нужен только один из них. Ссылки, которые другие предоставили, должны быть полезны при изучении шаблона Singleton.

Ответ 2

Singleton != Global. Кажется, вы ищете ключевое слово static.

Ответ 3

Синглтоны имеют смысл только в том случае, если оба этих условий верны:

  • Объект должен быть глобальным
  • Должен существовать только одиночный экземпляр объекта

Обратите внимание, что # 2 не означает, что вы хотите, чтобы объект имел только один экземпляр - если это так, просто создайте экземпляр только один раз - это означает, что должен (как в, это опасно для того, чтобы это не было правдой) только когда-либо был одним экземпляром.

Если вы хотите глобальный, просто сделайте глобальный экземпляр какого-либо (не стоящего) объекта (или сделайте его статическим или каким-либо другим). Если вы хотите только один экземпляр, снова статичным является ваш друг. Кроме того, просто создайте экземпляр только одного объекта.

Это мое мнение.

Ответ 4

Вы действительно можете упростить реализацию singleton, это то, что я использую:

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

    private static readonly FooService _instance = new FooService();

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

Ответ 5

Хм, все это кажется немного сложным.

Зачем вам нужна инфраструктура инъекций зависимостей, чтобы получить синглтон? Использование контейнера IOC отлично подходит для какого-либо корпоративного приложения (пока оно не используется чрезмерно), но, ах, парень просто хочет знать, что он реализует шаблон.

Почему бы не всегда с нетерпением создавать экземпляр, а затем предоставить метод, возвращающий статический, большая часть написанного выше кода затем уходит. Следуйте за старой C2-поговоркой - DoTheSimplestThingThatCouldPossiblyWork...

Ответ 7

Игнорируя вопрос о том, следует ли использовать шаблон Singleton, который обсуждался в другом месте, я бы выполнил одноэлемент:

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

    }

}

Ответ 8

Статический синглтон в значительной степени является анти-шаблоном, если вы хотите свободно связанный дизайн. Избегайте, если это возможно, и если это не очень простая система, я бы рекомендовал взглянуть на одну из доступных фреймворков инъекций зависимостей, таких как http://ninject.org/ или http://code.google.com/p/autofac/.

Чтобы зарегистрировать/использовать тип, сконфигурированный как singleton в autofac, вы сделали бы что-то вроде следующего:

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

Принятый ответ - это страшное решение, кстати, по крайней мере, проверьте тех, кто действительно реализовал шаблон.

Ответ 9

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

}

Ответ 10

Мне нравится этот шаблон, хотя он не мешает кому-либо создавать экземпляр, не являющийся одиночным. Иногда может быть лучше обучить разработчиков вашей команды использованию правильной методологии против героической длины, чтобы предотвратить неправильное использование вашего костяшка от вашего кода...

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

Это даст вам один экземпляр (созданный правильно) и будет эффективно лениться, потому что статический конструктор не получает вызов до вызова Build().

Ответ 11

То, что вы описываете, - это просто статические функции и константы, а не одиночные. Шаблон проектирования singleton (который очень редко необходим) описывает экземпляр класса, но только один раз, автоматически, когда он впервые используется.

Он объединяет ленивую инициализацию с проверкой, чтобы предотвратить множественные экземпляры. Это действительно полезно для классов, которые обертывают какое-то понятие, которое физически сингулярно, например обертка вокруг аппаратного устройства.

Статические константы и функции таковы: код, который вообще не нуждается в экземпляре.

Спросите себя: "Разве этот класс сломается, если есть несколько экземпляров?" Если ответ отрицательный, вам не нужен синглтон.

Ответ 12

hmmm... Немногие константы со связанными функциями... это не будет лучше достигнуто с помощью перечислений? Я знаю, что вы можете создать пользовательское перечисление в Java с помощью методов и всех, то же самое должно быть достигнуто в С#, если оно не поддерживается напрямую, тогда это можно сделать с помощью простого класса singleton с частным конструктором.

Если ваши константы семантически связаны, вы должны рассмотреть перечисления (или эквивалентную концепцию), вы получите все преимущества постоянных статических переменных +, которые вы сможете использовать в своих интересах для проверки типов компилятора.

Мой 2 цента

Ответ 13

Лично я хотел бы использовать инфраструктуру инъекций зависимостей, например Unity, и все они могут настраивать элементы singleton в контейнере и улучшать связь, переходя от зависимости класса к зависимости интерфейса.

Ответ 14

Скрывая открытый конструктор, добавляя приватное статическое поле для хранения этого единственного экземпляра и добавляя статический метод factory (с ленивым инициализатором) для возврата этого единственного экземпляра

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

Ответ 15

Я написал класс для моего проекта, используя шаблон Singleton. Он очень прост в использовании. Надеюсь, это сработает для вас. Пожалуйста, найдите следующий код.

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

Теперь вы можете установить значение переменной для вышеуказанного кода в своем приложении, как это.

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

И вы можете получить такое значение, как это.

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

Ответ 16

В С# это может быть (Thread safe, а также ленивая инициализация):

public sealed class MySingleton
{
    static volatile Lazy<MySingleton> _instance = new Lazy<MySingleton>(() => new MySingleton(), true);
    public static MySingleton Instance => _instance.Value;
    private MySingleton() { }
}