Использование Синглетона в приложении C#
Я провел последние пару дней, читая и пробуя различные методы для создания и использования синглетного экземпляра одного из моих файлов класса, а затем используя ссылку, как мне нужно на протяжении всей жизни программы здесь, на stackoverflow, а также на нескольких других сайтах, и обнаружил, что есть ооочень много мнений, предложений и примеров, которые работают, что я немного запутался, особенно когда дело доходит до фактического использования синглетного объекта.
У меня есть кое-что это работает, но я не думаю, что это самый правильный путь, и что я могу пропустить шаг.
У меня есть простой файл класса в моей программе под названием 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(@"SoftwareKey1Key2Key3");
dataBase = key.GetValue("ADODataSource").ToString().Trim();
userId = key.GetValue("ServerUserID").ToString().Trim();
passWord = key.GetValue("ServerPassword").ToString().Trim();
}
} // end class definition
Который при вызове из основного метода реализует корректно и вызывает один открытый метод (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());
}
}
После создания синглтона класса у меня загружается небольшая форма входа в систему, и я хочу, чтобы имя базы данных из синглтона отображалось в форме и вот тут-то у меня и нет более чем элегантного кода.
private void frmLogin_Load(object sender, EventArgs e)
{
// create a 'new' instance to the singleton?
clsRegistry regData = clsRegistry.GetInstance();
lblDataBase.Text = regData.dataBase;
}
Действительно ли мне нужно создать еще одну ссылку на мой синглетный объект, чтобы прочитать некоторые значения (или позже вызвать другой метод), или я где-то пропустил шаг? Я действую в предположении, что как только я создаю экземпляр класса как синглет, и он остается в том же пространстве имен, я могу получить доступ к любому общедоступному значению или методу. - Нет?
Для справки я использую Visual Studio 2010 и платформу 4.0 (и да Я еще один классический разработчик VB, который наконец-то прыгает с корабля)
3 ответов:
Прежде всего: в C# для этого не нужны блокировки и т. д. Просто создайте экземпляр с помощью статической инициализации,и вы будете threadsafe и хорошо идти.
После этого вы можете просто получить доступ к синглету и его свойствам / методам через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без необходимости сначала присваивать его новой переменной:static void Main() { ClsRegistry.Instance.ReadKeys(); // ... }И
private void frmLogin_Load(object sender, EventArgs e) { lblDataBase.Text = ClsRegistry.Instance.DataBase; }Пожалуйста, обратите внимание, что я изменил названия вашего класса и свойств так, чтобы каждая первая буква была заглавной, что является своего рода соглашение в C#
Во-первых, Microsoft имеет рекомендации для реализации синглтона конкретно в C#, что объясняет в мельчайших деталях лучший способ создания единого и многопоточного синглтонного класса.
Что касается вашего кода:
Вы не создаете другой экземпляр вашего объекта при вызове GetInstance. Код возвращает ранее созданный экземпляр. Он создает новый экземпляр класса только в том случае, если он равен null (только один раз).
Вы должны сделать Экземпляр свойства вместо метода в .NET (это просто чище).
Вы должны придерживаться Pascal case при написании кода .NET, если вы пишете код Java, я бы посоветовал вам придерживаться camelCase, потому что это стандартный корпус для языка.
Чтобы получить доступ к значениям, необходимо запросить ссылку на синглет, да. Вам не нужно хранить эту ссылку в локальной переменной, если вы не хотите, хотя вы, конечно, можете. Если вы не хотите, вы можете получить доступ к значению непосредственно из экземпляра:
lblDataBase.Text = clsRegistry.GetInstance().dataBase;
Comments