Вопрос

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

Это было полезно?

Решение

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

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

   public static string MangleString( string someValue )
   {
   }
}

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

Другие советы

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

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

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

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

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

    Это мое мнение в любом случае.

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

        internal FooService() { }        
        static FooService() { }
    
        private static readonly FooService _instance = new FooService();
    
        public static FooService Instance
        {
            get { return _instance; }
        }
    

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

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

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

    Я бы порекомендовал вам прочитать статью Изучение шаблона проектирования Singleton доступно на MSDN. В нем подробно описываются особенности инфраструктуры, которые упрощают реализацию шаблона.

    Кроме того, я бы ознакомился с связанной статьей о SO в отношении синглетонов .

    Игнорируя вопрос о том, следует ли использовать шаблон 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() {
    
        }
    
    }
    

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

    Чтобы зарегистрировать / использовать тип, настроенный как одноэлементный в 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>();
    

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

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

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

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

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

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

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

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

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

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

    Мои 2 цента

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

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

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

    Я написал класс для своего проекта, используя шаблон 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();
        }
    

    В c # это может быть (поточно-ориентированная и ленивая инициализация):

    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());
    }
    
    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top