zoukankan      html  css  js  c++  java
  • A Generic Singleton Class

    源文地址:http://www.fascinatedwithsoftware.com/blog/post/2011/07/13/A-Generic-Singleton-Class.aspx

    Much has been written about how to implement the Singleton pattern in C#. The basic idea, ignoring the aspects of thread-safety:

    • Make the default constructor private so the class cannot be instantiated directly.
    • Make a static member variable that holds the one instance of the class itself.
    • Make an Instance property that returns the static member.

    Version 4.0 of the .NET framework introduces the Lazy<T> class, which makes correct implementation easier and better than ever. But you still have to remember how to do it, so let's make it even easier and even better by encapsulating everything in a generic class.

    The Generic Singleton Class

    using System;
    using System.Linq;
    using System.Reflection;
      
    namespace SingletonDemo
    {
      public abstract class Singleton
      {
        private static readonly Lazy<T> _instance
          = new Lazy<T>(() =>
            {
              var ctors = typeof(T).GetConstructors(
                  BindingFlags.Instance
                  |BindingFlags.NonPublic
                  |BindingFlags.Public);
              if (ctors.Count() != 1)
                  throw new InvalidOperationException(String.Format("Type {0} must have exactly one constructor.",typeof(T)));
              var ctor = ctors.SingleOrDefault(c => c.GetParameters().Count() == 0 && c.IsPrivate);
              if (ctor == null)
                  throw new InvalidOperationException(String.Format("The constructor for {0} must be private and take no parameters.",typeof(T)));
              return (T)ctor.Invoke(null);
            });
      
        public static T Instance
        {
          get { return _instance.Value; }
        }
      }
    }
     

    Proceeding from top to bottom, we note the following:

    • The class is abstract so it cannot be created directly, but must be derived from.
    • The _instance member is a Lazy<T>, where T is the class for which we want a singleton. 
    • The Lazy class' constructor takes one parameter, which is the Func that produces the singleton.
    • In the well-known pattern, a Singleton class' constructor should be private. This forces consumers of the class to use the Instance property, which gets the one and only instance. Accordingly, our Func looks for a private constructor that takes no parameters.
    • Once our Func has ensured that all is well, it invokes the private, parameterless constructor. Don't worry about the time it takes to do an Invoke; it will only happen once!
    • The Instance property returns the one and only instance of the T class, according to the usual pattern.

    A Concrete Instance

    All you must do to use the generic Singleton class is

    • Inherit from Singleton<T> as shown below.
    • Provide a private constructor.
     
    • Provide a private constructor.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    using System.Threading;
    namespace SingletonDemo
    {
        class MySingleton : Singleton<MySingleton>
        {
            int _counter;
      
            public int Counter 
            
                get { return _counter; } 
            }
      
            private MySingleton()
            {
                _counter = 0;
            }
      
            public void IncrementCounter()
            {
                // ++_counter;   // BAD!!!
                Interlocked.Increment(ref _counter);
            }
        }
    }

    Although the Lazy<T> class ensures that the singleton is created in a thread-safe manner, that does not mean that the singleton itself is thread-safe! To underscore this fact, the listing of MySingleton shows how to increment the backing variable for its Counter property.

    Using the Singleton Instance

    You can now access the single instance of MySingleton with its Instance property. Here is an example. We execute a couple of nested loops, the outer one in parallel, to increment the counter in the singleton a total of 100,000 times. The program prints

    1
    Counter=100000.

    (By the way, if you change MySingleton.cs to use the BAD method of updating the counter, the final result will usually print as something less than 100000.)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    using System;
    using System.Collections.Generic;
    using System.Threading.Tasks;
      
    namespace SingletonDemo
    {
      class Program
      {
        static void Main(string[] args)
        {
          Parallel.For(0, 100, i =>
            {
              for (int j = 0; j < 1000; ++j)
                  MySingleton.Instance.IncrementCounter();
            });
      
          Console.WriteLine("Counter={0}.", MySingleton.Instance.Counter);
          Console.ReadLine();
        }
      }
    }

    Be the first to rate this post

    Simpler.

    using System;
    using System.Linq;
    using System.Reflection;

    namespace SingletonDemo
    {
      public class Singleton<T> where T : new ()
      {
        private static readonly Lazy<T> _instance
          = new Lazy<T>(() => new T());
            
        public static T Instance
        {
          get { return _instance.Value; }
        }
      }
    }

    Mika Piirainen Finland

    2011/9/11 13:58:38 #

    mikalai

    @ Mika

    Your example is not Singleton because Singleton<T> relies on public constructor. That means that more than one instance of T can be created.

  • 相关阅读:
    Mobox企业网盘回收站文件清空与恢复的管控
    NAS设备部署后采用Mobox企业云盘来提升管理功能
    企业网盘支持对象存储帮助用户推行私有云
    阿里云登录界面无法输入账号及密码的解决方法
    团队协作管理-任务追踪管理
    windows10 家庭版 无法远程2012的解决
    bat删除多少天前的文件包含子目录
    企业网盘居然支持高速局域网文件传输工具(速度可达20M)
    防范永恒之蓝勒索病毒-XP、Win10文件共享怎样设置
    【OpenGL】学习笔记#2
  • 原文地址:https://www.cnblogs.com/sail/p/2480751.html
Copyright © 2011-2022 走看看