Универсальный синглтон

Что вы, ребята, думаете об этом для универсального синглтона?

using System;
using System.Reflection;

// Use like this
/*
public class Highlander : Singleton<Highlander>
{
    private Highlander()
    {
        Console.WriteLine("There can be only one...");
    }
}
*/

public class Singleton<T> where T : class
{
    private static T instance;
    private static object initLock = new object();

    public static T GetInstance()
    {
        if (instance == null)
        {
            CreateInstance();
        }

        return instance;
    }

    private static void CreateInstance()
    {
        lock (initLock)
        {
            if (instance == null)
            {
                Type t = typeof(T);

                // Ensure there are no public constructors...
                ConstructorInfo[] ctors = t.GetConstructors();
                if (ctors.Length > 0)
                {
                   throw new InvalidOperationException(String.Format("{0} has at least one accesible ctor making it impossible to enforce singleton behaviour", t.Name));
                }

                // Create an instance via the private constructor
                instance = (T)Activator.CreateInstance(t, true);
            }
        }
    }
}
 Sanjeevakumar Hiremath03 мар. 2011 г., 12:12
Эта техника блокировки нарушена, если для объекта блокировки не используется ключевое слово volatile. Увидетьэтот
 Toon Krijthe19 дек. 2008 г., 12:43
+1 за имя Горец ;-)
 MPelletier31 мар. 2012 г., 19:24
Прекрасный вопрос для codereview.stackexchange.com

Ответы на вопрос(7)

Ну, это на самом деле не синглтон - так как вы не можете контролироватьTможет быть как многоT экземпляры, как вам нравится.

(удален гоночный поток; отмечен двойной контроль использования)

Решение Вопроса

Создание синглтон-класса - это всего лишь несколько строк кода, и с трудностями создания общего синглтона я всегда пишу эти строки кода.

public class Singleton
{
    private Singleton() {}
    static Singleton() {}
    private static Singleton _instance = new Singleton();
    public static Singleton Instance { get { return _instance; }}
}

private static Singleton _instance = new Singleton();

line устраняет необходимость в блокировке, так как статический конструктор является поточно-ориентированным.

 Jon Skeet19 дек. 2008 г., 12:46
Именно так. Тем более, что универсальная версия на самом деле не дает вам синглтон в любом случае ...
 Winston Smith19 дек. 2008 г., 12:48
Вы, вероятно, также должны добавить статический конструктор. Увидетьyoda.arachsys.com/csharp/singleton.html
 Alastair Pitts25 мар. 2013 г., 05:23
Я добавил статический конструктор в линию со связанной статьей Jon Skeet.
 Sanjeevakumar Hiremath03 мар. 2011 г., 12:12
Эта техника блокировки нарушена, если для объекта блокировки не используется ключевое слово volatile. Увидетьэтот
 Marc Gravell19 дек. 2008 г., 12:48
В самом деле. И для ленивой загрузки страница Джона покрывает это также вложенным классом.

Это моя точка зрения с использованием .NET 4

public class Singleton<T> where T : class, new()
    {
        Singleton (){}

        private static readonly Lazy<T> instance = new Lazy<T>(()=> new T());

        public static T Instance { get { return instance.Value; } } 
    }

и он использует следующее:

   public class Adaptor
   {
     public static Adaptor Instance { get { return Singleton<Adaptor>.Instance;}}
   }
 Alexandr24 авг. 2012 г., 12:29
Это стоимость его дженериков.
 sweetfa24 авг. 2012 г., 23:13
Да, просто нужно сделать очевидным для нуба, хотя
 Wouter09 авг. 2019 г., 23:42
Вы должны добавить частный конструктор в Adapter, который нарушает ваш дизайн.
 sweetfa23 авг. 2012 г., 00:55
Проблема с этим подходом состоит в том, что он требует открытого конструктора для класса реализации singleton, который допускает возможность использования вне границ одноэлементного экземпляра (то есть, здесь нет предупреждения о времени компиляции).

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

Так,Вы не можете создать универсальную фабрику синглтонов - она ​​подрывает сам шаблон.

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

Кроме того, это не запрещаетвнутренний конструкторы - так что вы можете получить не синглетоны.

Я бы лично создал экземпляр в статическом конструкторе для обеспечения безопасности простых потоков.

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

 fourpastmidnight20 июл. 2012 г., 05:45
@kenny: Мне нужна именно эта ссылка. Спасибо!!
 Marc Gravell19 дек. 2008 г., 13:04
Согласовано; в большинстве случаев статический класс является более подходящим. Полезно для реализации интерфейсов и т. Д., Но стандартный шаблон работает нормально, не требуя обобщений.
 kenny20 июл. 2012 г., 06:53
Обновленная ссылкаcsharpindepth.com/Articles/General/Singleton.aspx
 kenny19 дек. 2008 г., 14:35
Не забудь ссылку ... Джон! :)yoda.arachsys.com/csharp/singleton.html

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

public sealed class Adaptor
{
    private static readonly Lazy<Adaptor> instance = new Lazy<Adaptor>(() => new Adaptor());

    public static Adaptor Instance { get { return instance.Value; } }

    private Adaptor() { }
}

Вы не можете правильно преобразовать это в отдельный общий синглтон.

Смотрите также:http://csharpindepth.com/Articles/General/Singleton.aspx

Четвертая версия - не такая ленивая, но поточно-ориентированная без использования замков"реализации Singleton c #, почему бы не использовать фрагмент кода для выполнения всей тяжелой работы:

<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
    <CodeSnippet Format="1.0.0">
        <Header>
            <Title>Singleton Class</Title>
            <Author>TWSoft</Author>
            <Description>Generates a singleton class</Description>
            <SnippetTypes>
                <SnippetType>Expansion</SnippetType>
            </SnippetTypes>
            <Keywords>
                <Keyword>Singleton</Keyword>
            </Keywords>
            <Shortcut>singleton</Shortcut>
        </Header>
        <Snippet>
            <Declarations>
                <Literal>
                    <ID>ClassName</ID>
                    <ToolTip>Replace with class name</ToolTip>
                    <Default>MySingletonClass</Default>
                </Literal>
            </Declarations>

            <Code Language="CSharp">
                <![CDATA[
                public class $ClassName$
                {
                    #region Singleton
                    static readonly $ClassName$ mInstance = new $ClassName$();

                    // Explicit static constructor to tell C# compiler
                    // not to mark type as beforefieldinit
                    static $ClassName$()
                    {
                    }

                    private $ClassName$()
                    {
                    }

                    public static $ClassName$ Instance
                    {
                        get { return mInstance; }
                    }
                #endregion
                }
                ]]>
            </Code>
        </Snippet>
    </CodeSnippet>
</CodeSnippets>

Затем вы можете сохранить это в файл .snippt и добавить его в VS IDE (Инструменты-> Диспетчер фрагментов кода)

Ваш ответ на вопрос