在C#应用程序中使用Singleton

本文关键字:Singleton 应用程序 | 更新日期: 2023-09-27 18:13:10

在过去的几天里,我一直在阅读并尝试不同的方法来创建和使用我的一个类文件的单例实例,然后在stackoverflow和其他一些网站上使用我在整个程序生命周期中需要的引用,我发现有太多的意见,工作的建议和示例,我有点困惑,尤其是在实际使用singleton对象时。

我有一些功能,但我不认为这是最正确的方式,我可能会错过一步。

我的程序中有一个简单的类文件,名为clsRegistry,实现为单例。

public sealed class clsRegistry
{
  //http://tech.pro/tutorial/625/csharp-tutorial-singleton-pattern
  private static clsRegistry RegInstance;
  private clsRegistry() { }
  public static clsRegistry GetInstance()
  {
    lock (typeof(clsRegistry))
    {
      if (RegInstance == null)
      {
        RegInstance = new clsRegistry();
      }
      return RegInstance;
    }
  }
  public string dataBase { get; set; }
  public string userId { get; set; }
  public string passWord { get; set; }
  public void ReadKeys()
  {
    //http://stackoverflow.com/questions/1388787/information-in-registry
    RegistryKey key = Registry.LocalMachine.OpenSubKey(@"Software'Key1'Key2'Key3");
    dataBase = key.GetValue("ADODataSource").ToString().Trim();
    userId = key.GetValue("ServerUserID").ToString().Trim();
    passWord = key.GetValue("ServerPassword").ToString().Trim();
  }
}   // end class definition

当从Main方法调用时,正确实现并调用类中的一个公共方法(ReadKeys(

static class Program
{
  /// <summary>
  /// The main entry point for the application.
  /// </summary>
  [STAThread]
  static void Main()
  {
    // create instance of registry class 
    clsRegistry regData = clsRegistry.GetInstance();
    // call method
    regData.ReadKeys();
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    //Application.Run(new frmMain());
    Application.Run(new frmLogin());
  }
}

在创建了类的singleton之后,我加载了一个小的登录表单,我希望singleton中的数据库名称显示在表单中,这就是我拥有不太优雅代码的地方。

private void frmLogin_Load(object sender, EventArgs e)
{
  // create a 'new' instance to the singleton?
  clsRegistry regData = clsRegistry.GetInstance();
  lblDataBase.Text = regData.dataBase;
}

我真的需要创建另一个对我的singleton对象的引用来读取一些值吗(或者稍后调用另一个方法(,或者我在哪里错过了一个步骤?我的操作假设是,一旦我创建了一个类的实例作为单例,并且它保持在同一个命名空间中,我就可以访问任何公共值或方法。不

作为参考,我使用的是Visual Studio 2010和4.0框架(是的,我是另一个经典的VB开发人员,终于跳槽了(

在C#应用程序中使用Singleton

首先,微软有专门在C#中实现单例的指导方针,详细解释了创建单线程和多线程单例类的最佳方法。

就您的代码而言:

  1. 调用GetInstance时,您没有创建对象的另一个实例。该代码返回以前创建的实例。只有当类的一个新实例为null时(仅一次(,它才会实例化该实例。

  2. 您应该将Instance作为一个属性,而不是.NET中的一个方法(它更干净(。

  3. 在编写.NET代码时,您应该坚持使用Pascal大小写,如果您正在编写Java代码,我建议您坚持使用camelCase,因为这是该语言的标准大小写。

首先:在C#中,您不需要锁等。只需通过静态初始化创建实例,就可以确保线程安全,并且可以继续使用。

public sealed class ClsRegistry
{
    private static ClsRegistry RegInstance = new ClsRegistry();
    private clsRegistry() { }
    public static ClsRegistry Instance {
        get { return RegInstance; }
    }
    public string DataBase { get; set; }
    public string UserId { get; set; }
    public string PassWord { get; set; }
    public void ReadKeys()
    {
        // ...
    }
}

话虽如此,您可以通过ClsRegistry.Instance简单地访问singleton及其属性/方法,而无需首先将其分配给新变量:

static void Main()
{
    ClsRegistry.Instance.ReadKeys();
    // ...
}

private void frmLogin_Load(object sender, EventArgs e)
{
    lblDataBase.Text = ClsRegistry.Instance.DataBase;
}

请注意,我更改了类和属性的名称,使每个第一个字母都是大写字母,这是C#中的一种约定

您需要向singleton请求其引用来访问值,是的。如果您不想将该引用存储在局部变量中,则不需要存储,尽管您当然可以。如果你不想,你可以直接从实例中访问值:

lblDataBase.Text = clsRegistry.GetInstance().dataBase;