用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,  null new  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,
                                          
null new  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,
                                      
null new  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个警告。希望有经验的人,能说说自己的理解。先谢过了!

 

转载于:https://www.cnblogs.com/wanghui9072229/archive/2011/03/08/1977025.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值