Объект конфигурации из пар имя-значение - PullRequest
0 голосов
/ 04 октября 2011

Я работаю над веб-приложением, которое должно хранить и обновлять конфигурации в базе данных. Например, я могу сохранить пользовательские настройки, такие как цвета по умолчанию, языки, предпочтительные форматы даты и т. Д.

Таблица базы данных состоит из пар имя / значение (nvarchars). Достаточно просто.

Я использую ORM для извлечения списка - фактически IEnumerable - из этих пар строк имя / значение. Моя проблема в том, что мне нужно превратить эти IEnumerable во что-то более выразительное, чем строки имен / значений. То есть я хочу создать строго типизированный объект конфигурации.

В идеале я хотел бы сделать так, чтобы этот объект конфигурации не имел прямой зависимости от ORM, но я не уверен, как это сделать, так как инициализация этого объекта и сохранение пользовательские настройки должны пройти через ORM.

Какой-то шаблон дизайна на помощь?

(Это не должно иметь значения, но я использую C # и Entity Framework.)


EDIT:

Допустим, у меня есть следующие поля в объектах моего домена:

public class SettingNameValuePair {
    public string Name {get;set;}
    public string Value {get;set;}
}

public class GlobalSettings {
    public System.Drawing.Color FontColor {get;set;}
    public TimeZoneInfo DefaultTimeZone {get;set;}
    public DateTime DateCreated {get;set;}

    ... constructor ...
    ... validation, other functions ...
}

Я могу настроить свой ORM для загрузки и сохранения SettingNameValuePair без особых усилий. Тем не менее, как я могу получить и сохранить GlobalSettings? То есть где-то в моем приложении я хочу получить экземпляр моих глобальных настроек.

using (var context = new ApplicationContext()) {    
    GlobalSettings settings = ???
}

ORM, конечно, не будет знать, как автоматически конвертировать между SettingNameValuePair и GlobalSettings. Я знаю, что мне нужно будет написать некоторый «слесарный» код для создания строго типизированных свойств GlobalSettings.

Мой вопрос: каков хороший способ вернуть экземпляр GlobalSettings, который заполняется SettingNameValuePair? Вот два варианта, безусловно, ошибочны:

1) Пусть конструктор GlobalSettings примет контекст данных в качестве аргумента. Это создает плохую зависимость и ее трудно проверить.

2) Пусть конструктор GlobalSettings возьмет SettingNameValuePair из контекста данных следующим образом:

using (var context = new ApplicationContext()) {    
    IEnumerable<SettingNameValuePair> nameValuePairs = 
        context.NameValuePairs.ToList();
    GlobalSettings settings = new GlobalSettings(nameValuePairs);
}

Проблема в том, что вы должны повторять этот код повсюду.

У меня такое ощущение, что есть лучшие решения, которые включают синглтоны, статические классы, прокси или методы Factory, но мне пока не нравятся эти концепции.

Ответы [ 2 ]

1 голос
/ 04 октября 2011

Не ссылайтесь на свой ORM в своем доменном объекте, вместо этого внедрите его в репозиторий, который будет использовать либо ваш ORM, либо любые другие методы доступа к данным (например, устройство чтения данных, так как большинство форм не смогут отобразить пару пары ключ-значение истрого типизированные объекты).

также я не рекомендую давать объекту (globalsettings) пару значений ключа в конструкторе, поскольку она не связана с доменом, сопоставьте пары значений ключей с объектом домена, вместо этого реализуйте отображение вслой отображения, который является вашим хранилищем или dal

, например:

на прикладном уровне

public GlobalSettings GetUserSettings(User user)
{
  return _globalSettingsRepository.GetGlobalSettings(user);
}

на уровне хранилища

public GlobalSettings GetGlobalSettings(User user)
{
  var keyvalue = _context.blablabla();
  var globalSettings = new GlobalSettings { Id = keyvalue["key"], DateCreated = DateTime.Parse(keyvalue["datecreated"]) };
  return globalSettings
}
0 голосов
/ 04 октября 2011

Я не думаю, что существует какой-либо ORM, который сопоставляется с парами ключ-значение.Фактически, вероятно, было бы более эффективно использовать DataReader для этих данных.Однако, как вы получаете данные, вы можете просто использовать ваши конфигурационные KVP для создания словаря, а затем использовать Property Pattern для доступа.Затем вы можете создать строго типизированные методы доступа для свойств, которые, как вы знаете, вам понадобятся.Это позволит вам использовать строго типизированные объекты для свойств, о которых вы знаете, при этом сохраняя гибкость добавления свойств без изменения кода.

...