Каков хороший шаблонный шаблонный шаблон в C # - PullRequest
30 голосов
/ 19 сентября 2008

У меня есть следующий шаблон C # singleton, есть ли способ улучшить его?

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

        private static object _syncobj = new object();
        private static volatile T _instance = null;
        public static T Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (_syncobj)
                    {
                        if (_instance == null)
                        {
                            _instance = new T();
                        }
                    }
                }
                return _instance;
            }
        }

        public Singleton()
        { }

    }

Пример предпочтительного использования:

class Foo : Singleton<Foo> 
{
} 

Связано :

Очевидная одноэлементная реализация для .NET?

Ответы [ 22 ]

1 голос
/ 19 сентября 2008
public sealed class Singleton
{
   private static readonly Singleton instance = new Singleton();

   private Singleton(){}

   public static Singleton Instance
   {
      get 
      {
         return instance; 
      }
   }
}

В .NET нет никакой двусмысленности в отношении порядка инициализации ; но это вызывает проблемы с многопоточностью.

1 голос
/ 15 мая 2009

Я искал лучшую модель синглтона, и мне понравился этот. Так что портировал его на VB.NET, может пригодиться другим:

Public MustInherit Class Singleton(Of T As {Class, New})
    Public Sub New()
    End Sub

    Private Class SingletonCreator
        Shared Sub New()
        End Sub
        Friend Shared ReadOnly Instance As New T
    End Class

    Public Shared ReadOnly Property Instance() As T
        Get
            Return SingletonCreator.Instance
        End Get
    End Property
End Class
0 голосов
/ 04 июля 2018

Не важно, какой пример вы выберете, всегда проверяйте параллелизм, используя Parallel.For! (цикл, в котором итерации могут выполняться параллельно)

положить в синглтон C'tor:

 private Singleton ()
        {
            Console.WriteLine("usage of the Singleton for the first time");
        }

положить в основной:

Parallel.For(0, 10,
              index => {
                  Thread tt = new Thread(new ThreadStart(Singleton.Instance.SomePrintMethod));
                  tt.Start();
              });
0 голосов
/ 14 сентября 2017

Это работает для меня:

public static class Singleton<T> 
{
    private static readonly object Sync = new object();

    public static T GetSingleton(ref T singletonMember, Func<T> initializer)
    {
        if (singletonMember == null)
        {
            lock (Sync)
            {
                if (singletonMember == null)
                    singletonMember = initializer();
            }
        }
        return singletonMember;
    }
}

Использование:

private static MyType _current;
public static MyType Current = Singleton<MyType>.GetSingleton(ref _current, () => new MyType());

Потребление синглтона:

MyType.Current. ...
0 голосов
/ 22 января 2013

Как в Википедии :

шаблон синглтона - это шаблон проектирования, который ограничивает создание экземпляра класса для одного объекта

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

public class MyClass
{
        private MyClass()
        {

        }

        static MyClass()
        {
            Instance = new MyClass();
        }

        public static MyClass Instance { get; private set; }
}

OR:

public class MyClass
    {
            private MyClass()
            {

            }

            static MyClass()
            {
                Instance = new MyClass();
            }

            private static MyClass instance;



            public static MyClass Instance
            {
                get
                {
                    return instance;
                }
                private set
                {
                    instance = value;
                }
            }
    }
0 голосов
/ 19 сентября 2008

Мне очень понравился ваш оригинальный ответ - единственное, чего не хватает (по ссылке, опубликованной blowdart), это сделать переменную _instance энергозависимой, чтобы убедиться, что она действительно была установлена ​​в блокировке. Я на самом деле использую решение Blowdarts, когда мне нужно использовать синглтон, но у меня нет необходимости опаздывать и т. Д.

0 голосов
/ 09 октября 2011

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

public class Singleton<T> where T : class
{
    class SingletonCreator
    {
        static SingletonCreator() { }

        internal static readonly T Instance =
            typeof(T).InvokeMember(typeof(T).Name,
                                    BindingFlags.CreateInstance |
                                    BindingFlags.Instance |
                                    BindingFlags.Public |
                                    BindingFlags.NonPublic,
                                    null, null, null) as T;
    }

    public static T Instance
    {
        get { return SingletonCreator.Instance; }
    }
}

Предполагаемая реализация:

public class Foo: Singleton<Foo>
{
     private Foo() { }
}

Тогда:

Foo.Instance.SomeMethod();
0 голосов
/ 25 сентября 2009

Некоторое время назад видел один, который использует отражение для доступа к частному (или общедоступному) конструктору по умолчанию:

public static class Singleton<T>
{
    private static object lockVar = new object();
    private static bool made;
    private static T _singleton = default(T);

    /// <summary>
    /// Get The Singleton
    /// </summary>
    public static T Get
    {
        get
        {
            if (!made)
            {
                lock (lockVar)
                {
                    if (!made)
                    {
                        ConstructorInfo cInfo = typeof(T).GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[0], null);
                        if (cInfo != null)
                            _singleton = (T)cInfo.Invoke(new object[0]);
                        else
                            throw new ArgumentException("Type Does Not Have A Default Constructor.");
                        made = true;
                    }
                }
            }

            return _singleton;
        }
    }
}
0 голосов
/ 25 сентября 2009
public static class LazyGlobal<T> where T : new()
{
    public static T Instance
    {
        get { return TType.Instance; }
    }

    private static class TType
    {
        public static readonly T Instance = new T();
    }
}

// user code:
{
    LazyGlobal<Foo>.Instance.Bar();
}

Или:

public delegate T Func<T>();

public static class CustomGlobalActivator<T>
{
    public static Func<T> CreateInstance { get; set; }
}

public static class LazyGlobal<T>
{
    public static T Instance
    {
        get { return TType.Instance; }
    }

    private static class TType
    {
        public static readonly T Instance = CustomGlobalActivator<T>.CreateInstance();
    }
}

{
    // setup code:
    // CustomGlobalActivator<Foo>.CreateInstance = () => new Foo(instanceOf_SL_or_IoC.DoSomeMagicReturning<FooDependencies>());
    CustomGlobalActivator<Foo>.CreateInstance = () => instanceOf_SL_or_IoC.PleaseResolve<Foo>();
    // ...
    // user code:
    LazyGlobal<Foo>.Instance.Bar();
}
0 голосов
/ 30 мая 2009

пфф ... снова ... :)
Мой вклад в обеспечение создания данных по запросу:


/// <summary>Abstract base class for thread-safe singleton objects</summary>
/// <typeparam name="T">Instance type</typeparam>
public abstract class SingletonOnDemand<T> {
  private static object __SYNC = new object();
  private static volatile bool _IsInstanceCreated = false;
  private static T _Instance = default(T);

  /// <summary>Instance data</summary>
  public static T Instance {
    get {
      if (!_IsInstanceCreated)
        lock (__SYNC)
          if (!_IsInstanceCreated) {
            _Instance = Activator.CreateInstance<T>();
            _IsInstanceCreated = true;
          }
          return _Instance;
    }
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...