Как реализовать синглтон в C #? - PullRequest
24 голосов
/ 29 октября 2008

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

Ответы [ 17 ]

28 голосов
/ 29 октября 2008

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

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

   public static string MangleString( string someValue )
   {
   }
}

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

7 голосов
/ 29 октября 2008

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

5 голосов
/ 29 октября 2008

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

  1. Объект должен быть global
  2. Должен существовать только единственный экземпляр объекта

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

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

Это все равно мое мнение.

4 голосов
/ 30 октября 2008

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

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

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

4 голосов
/ 29 октября 2008

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

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

    private static readonly FooService _instance = new FooService();

    public static FooService Instance
    {
        get { return _instance; }
    }
3 голосов
/ 29 октября 2008

Статический синглтон является в значительной степени анти-паттерном, если вы хотите слабо связанный дизайн. Избегайте, если возможно, и, если это не очень простая система, я бы рекомендовал взглянуть на одну из многих доступных структур внедрения зависимостей, таких как http://ninject.org/ или http://code.google.com/p/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>();

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

3 голосов
/ 29 октября 2008

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

    }

}
3 голосов
/ 29 октября 2008

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

Кроме того, я бы ознакомился с связанным чтением на SO, касающимся синглетонов .

2 голосов
/ 21 декабря 2008

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

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

2 голосов
/ 17 декабря 2008
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); }
    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...