用C#语言泛化单件模式

用C#语言泛化单件模式

 

本人对于C#只能算是初学者,写此随笔,也只为和大家一起讨论,共同进步。

 

我看到过一些用C#语言泛化单件(Singleton)的文章和代码,里面有个问题,即用new来创建对象,比如类似下面这段代码:

 

if (_instance ==  null)
{
    _instance =  new T();
}

 

要想让其工作,你必须让T的构造函数为public。但是,如果T的构造函数为public,那任何客户代码都可调用new T()。你无法用语言本身限制其只能被创建最多一次和只有一个全局访问点,这样也就无法保证你的单件成为“单件”。

 

C++里有友元(friend),T的构造函数可是设为non-public,然后用单件的模板类作为友元去访问它。用ACE的单件模板类ACE_Singleton时,就是如此实现。但C#没有友元。

 

CodeProject有篇文章:Generic Singleton Pattern using Reflection, in C#。作者用.Net反射机制实现了泛化的单件,重要的是它可以用具有non-public构造函数的public类来实例化。他用Type.GetConstructor来找到non-public的构造函数,并调用它来创建实例。他的代码如下(我去掉了异常处理部分):

 

ConstructorInfo constructor =  typeof(T).GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic,  nullnew Type[ 0],  null);
instance = (T)constructor.Invoke( null);

 

我仿照它写了我自己的泛化Singleton,见下:

 

复制代码
     public  static  class Singleton<T>  where T :  class
    {
         private  static  volatile T _instance;
         private  static  object _lock =  new  object();

         public  static T Instance
        {
             get
            {
                 if (_instance ==  null)
                {
                     lock (_lock)
                    {
                         if (_instance ==  null)
                        {
                            Type type =  typeof(T);
                            ConstructorInfo ctor;
                            ctor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
                                           nullnew Type[ 0],  new ParameterModifier[ 0]);
                            _instance = (T)ctor.Invoke( new  object[ 0]);
                        }
                    }
                }

                 return _instance;
            }
        }
    }
复制代码

 

当使用它时,客户代码是这样的:

 

复制代码
     public  sealed  class ZoomTool : BaseTool
    {
         #region Constructor

         private ZoomTool()
        {
        }

         #endregion

         #region Properties

        ......

         public  static ZoomTool Instance
        {
             get {  return Singleton<ZoomTool>.Instance; }
        }

         #endregion
    }
复制代码

 

使用ZoomTool单件时代码是这样:

 

_mapToolTypeToTool.Add(ToolType.Zoom, ZoomTool.Instance); 

 

但是这种泛型单件有一个问题:我得到了Code Analysis的CA1000警告:“不要在泛型类型中声明静态成员(Do not declare static members on generic types)”。

 

于是我将泛型类Singleton<T>改为普通类,将其中的Instance函数改为GetInstance<T>泛型函数,写下了另一个泛化的单件。

 

复制代码
     public  static  class Singleton
    {
         private  static  class Storage<T>  where T :  class
        {
             internal  static  volatile T _instance;
        }

         private  static  object _lock =  new  object();

        [System.Diagnostics.CodeAnalysis.SuppressMessage( " Microsoft.Design "" CA1004:GenericMethodsShouldProvideTypeParameter ")]
         public  static T GetInstance<T>()  where T :  class
        {
             if (Storage<T>._instance ==  null)
            {
                 lock (_lock)
                {
                     if (Storage<T>._instance ==  null)
                    {
                        Type type =  typeof(T);
                        ConstructorInfo ctor;
                        ctor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
                                       nullnew Type[ 0],  new ParameterModifier[ 0]);
                        Storage<T>._instance = (T)ctor.Invoke( new  object[ 0]);
                    }
                }
            }
             return Storage<T>._instance;
        }
    }
}
复制代码

 

这时客户代码是这样的:

 

复制代码
     public  sealed  class ZoomTool : BaseTool
    {
         #region Constructor

         private ZoomTool()
        {
        }

         #endregion

         #region Properties

        ......

         public  static ZoomTool Instance
        {
             get {  return Singleton.GetInstance<ZoomTool>(); }
        }

         #endregion
    }
复制代码

 

但我得到了另一个Code Analysis警告CA1004:“泛型方法应提供类型参数(Generic methods should provide type parameter)”。

 

MSDN里不推荐压制这两个消息(SuppressMessage),我感觉是泛型技术里有些规则限制的。我不太明白为什么要提示这2个警告。希望有经验的人,能说说自己的理解。先谢过了!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值