我正在尝试实施Singleton Pattern。
这是我到目前为止所做的:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MySql.Data.MySqlClient;
namespace POS
{
public sealed class Settings
{
private static Settings instance = null;
private static readonly object padlock = new object();
//System Variables
public string SYSTEM_NAME { get; set; }
public Settings()
{
//start new connection to the database
dbConnetion db = new dbConnetion();
string sql = " SELECT system_name "
+ " FROM configuration "
+ " LIMIT 1";
//read the system variable
foreach (var i in db.getData(sql, null, r =>
new globalSettings()
{
_sys_name = r["system_name"].ToString()
}
)
)
{
SYSTEM_NAME = i._sys_name;
}
}
public static Settings Instance
{
get
{
lock (padlock)
{
if (instance == null)
{
instance = new Settings();
}
return instance;
}
}
}
}
class globalSettings
{
public string _sys_name;
}
}
当我想读取变量时,我会这样做:
GlobalName.Text = Settings.SYSTEM_NAME;
但这不起作用。 我收到以下错误:
错误1非静态字段,方法或属性'POS.Settings.SYSTEM_NAME.get'
需要对象引用
如何正确读取变量?我是否也设法正确实现了Singleton模式?
答案 0 :(得分:4)
在您的代码中,您需要:
GlobalName.Text = Settings.Instance.SYSTEM_NAME;
这将实例化单例(如果它不存在),并允许您使用其实例(存储在Instance
静态属性中)。
为了存储这些属性,可以在C#中使用更简单的模式:
public static class Settings
{
public static string SystemName { get; set; }
public const string SomeOtherProperty = "x";
public static int AnotherOne
{
get
{
return 42;
}
}
}
然而,请注意,此类全局对象会引入隐藏的依赖关系,使您的代码难以维护(一个地方的更改可能会影响代码中的远处,非显而易见的位置。 - 如果所有属性都是常量,则不太明显)并且更难以测试(你不能存根/模拟单例)。
使您的实施更清洁:
您的班级违反了Single Responsibility Principle:您应该将DB中的配置与简单聚合的对象分开阅读。
明确依赖配置。例如,需要配置的每个类都应该在构造函数中接受它的实例并将其用于其目的。这样,您还可以轻松地测试此类,为不同的设置提供不同的配置和测试行为。
然后,您可以在不使用数据库的情况下测试您的类,但使用一些硬编码设置。想象一下,您有时可能想要从文件或命令行读取设置。