主页 > 编程资料 > C# >
发布时间:2015-09-26 作者:网络 阅读:267次
  很多情况下,我们需要一个Singleton窗体,比如,任务管理器就可以是windows应用系统中的一个Singleton,于是我们这样做:在窗体类的实现中添加一个静态指向单件的成员,提供一个静态的CreateInstance方法,当第一次调用此方法时创建单件。另外还要处理Closing事件,以使点击窗体右上角的“×”时,隐藏窗体。每次需要实现一个单件窗体时都要这么做,于是我决定写一个基类ISingletonDisplayer,一个窗体不用作任何改变,只需要将原来的基类Form改为ISingletonDisplayer就变成一个Singleton窗体,这就很方便了。先给出在VS2003中的实现。

public class ISingletonDisplayer : Form  //从Form继承
 {
  private static ISingletonDisplayer singleton = null ;
  private static bool toClean = false ;

  protected ISingletonDisplayer()
  {
   this.Closing += new System.ComponentModel.CancelEventHandler(ISingletonDisplayer_Closing,',',');
  }

  #region static for singleton

  #region GetSingleton
  public static ISingletonDisplayer GetSingleton()
  {
   if(ISingletonDisplayer.singleton != null)
   {
    ISingletonDisplayer.singleton.Visible = true ;
   }
   return ISingletonDisplayer.singleton ;
  }

  #endregion

  #region ReCreateSingleton

  //formOnUI存在是因为窗体只能在主线程(UI线程)中创建。
  public static void ReCreateSingleton(Type targetType ,object[] args , Form formOnUI)
  {
   Type supType = typeof(ISingletonDisplayer) ;
   if(! supType.IsAssignableFrom(targetType))
   {
    throw new Exception("Target type is not derived from ISingletonDisplayer !") ;
   }

   if(formOnUI.InvokeRequired)
   {
    object[] paras = {targetType ,args ,formOnUI} ;
    formOnUI.Invoke(new CBackCreateForm(ISingletonDisplayer.ReCreateSingleton) ,paras) ;
   }
   else
   {
    try
    {
     ISingletonDisplayer.toClean = false ;
     ISingletonDisplayer.singleton  = (ISingletonDisplayer)Activator.CreateInstance(targetType ,args) ;
     ISingletonDisplayer.singleton.Visible = false ;
    }
    catch(Exception ee)
    {
     throw ee ;
    }
   }
  }
  #endregion

  #region DestroySingleton
  public static void DestroySingleton()
  {
   ISingletonDisplayer.toClean = true ;
   if(ISingletonDisplayer.singleton != null)
   {
    ISingletonDisplayer.singleton.Close() ;
    ISingletonDisplayer.singleton = null ;
   }
  }
  #endregion

  #endregion

  #region ISingletonDisplayer_Closing
  private void ISingletonDisplayer_Closing(object sender, System.ComponentModel.CancelEventArgs e)
  {
   if(! ISingletonDisplayer.toClean)
   {
    this.Visible = false ;
    e.Cancel = true ;
    return ;
   }
  }
  #endregion
 }

 internal delegate void CBackCreateForm(Type targetType ,object[] args  , Form formOnUI) ;

  * 使用方法:
  * 如果一个Displayer需要以Singleton模式呈现,那么可以先以常规的方式设计Displayer,设计过程中不需要涉及任何与单件
  * 相关的东西。设计完后,只要将Displayer的基类由Form改为ISingletonDisplayer即可。接下来即可以单件的模式使用Displayer了。
  *
  * 如:
  * public class AppServersInfoForm2 : ISingletonDisplayer{}
  * object[] args = {obj} ;
  * ISingletonDisplayer.ReCreateSingleton(typeof(AppServersInfoForm2) ,args ,formOnUI) ;
    
 

上面的实现很容易理解,但是上面的实现有一个弊病,因为所有的单件窗体都要公用一个静态的ISingletonDisplayer singleton 成员,所以一个应用程序中只能有一个单件继承自ISingletonDisplayer。/ 在VS2005中可以使用泛型突破此限制。 

下面在看看在VS2005中的实现。

 public class ISingletonDisplayer : Form
 {
  private static ISingletonDisplayer singleton = null ;
  private static bool toClean = false ;

  protected ISingletonDisplayer()
  {
   this.Closing += new System.ComponentModel.CancelEventHandler(ISingletonDisplayer_Closing,',',');
  }

  public static ISingletonDisplayer GetSingleton()
  {
   if(ISingletonDisplayer.singleton != null)
   {
    ISingletonDisplayer.singleton.Visible = true ;
   }
   return ISingletonDisplayer.singleton ;
  }

  public static void ReCreateSingleton(Type targetType ,object[] args , Form formOnUI)
  {
   Type supType = typeof(ISingletonDisplayer) ;
   if(! supType.IsAssignableFrom(targetType))
   {
    throw new Exception("Target type is not derived from ISingletonDisplayer !") ;
   }

   if(formOnUI.InvokeRequired)
   {
    object[] paras = {targetType ,args ,formOnUI} ;
    formOnUI.Invoke(new CBackCreateForm(ISingletonDisplayer.ReCreateSingleton) ,paras) ;
   }
   else
   {
    try
    {
     ISingletonDisplayer.toClean = false ;
     ISingletonDisplayer.singleton  = (ISingletonDisplayer)Activator.CreateInstance(targetType ,args) ;
     ISingletonDisplayer.singleton.Visible = false ;
    }
    catch(Exception ee)
    {
     throw ee ;
    }
   }
  }

  public static void DestroySingleton()
  {
   ISingletonDisplayer.toClean = true ;
   if(ISingletonDisplayer.singleton != null)
   {
    ISingletonDisplayer.singleton.Close() ;
    ISingletonDisplayer.singleton = null ;
   }
  } 
  
  private void ISingletonDisplayer_Closing(object sender, System.ComponentModel.CancelEventArgs e)
  {
   if(! ISingletonDisplayer.toClean)
   {
    this.Visible = false ;
    e.Cancel = true ;
    return ;
   }
  }
 
    }
 

    internal delegate void CBackCreateForm(Type targetType ,object[] args  , Form formOnUI) ;

    如:
    public class AppServersInfoForm2 : ISingletonDisplayer{}
    object[] args = {obj} ;
    ISingletonDisplayer.ReCreateSingleton(typeof(AppServersInfoForm2) ,args ,this) ;

这样每个单件都有自己的静态实例,就不会相互干扰了。

如果你有更好的实现方法,欢迎和我讨论


关键字词: