Я работаю над веб-приложением, которое должно хранить и обновлять конфигурации в базе данных. Например, я могу сохранить пользовательские настройки, такие как цвета по умолчанию, языки, предпочтительные форматы даты и т. Д.
Таблица базы данных состоит из пар имя / значение (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, но мне пока не нравятся эти концепции.