来自名称值对的配置对象

时间:2011-10-04 13:42:46

标签: .net design-patterns architecture configuration name-value

我正在开发一个需要在数据库中存储和更新配置的Web应用程序。例如,我可能会存储用户首选项,如默认颜色,语言,首选日期格式等。

数据库表由名称/值对(nvarchars)组成。很简单。

我正在使用ORM来获取这些名称/值字符串对的列表 - 实际上是IEnumerable。我的问题是我需要将这些IEnumerable转换为比名称/值字符串更具表现力的东西。也就是说,我想制作一个强类型的配置对象。

理想情况下,我想这样做,以便这个配置对象没有对ORM的直接依赖,但我不知道如何去做,因为这个对象的初始化和持久性用户首选项需要通过ORM。

某种拯救的设计模式?

(应该没关系,但我正在使用C#和实体框架。)


修改

假设我的域对象中有以下字段:

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的强类型属性。

我的问题是:什么是获取由SettingNameValuePair填充的GlobalSettings实例的好方法?以下两种选择肯定是错误的:

1)让GlobalSettings的构造函数将数据上下文作为参数。这会引入不良依赖,难以测试。

2)让GlobalSettings的构造函数从数据上下文中获取SettingNameValuePair,如下所示:

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

这个问题是你必须在整个地方重复这段代码。

我觉得有更好的解决方案涉及单身人士,静态类,代理或工厂方法,但我对这些概念不满意。

2 个答案:

答案 0 :(得分:1)

不要在您的域对象中引用您的ORM,而是在存储库中实现它,该存储库将使用您的ORM或任何数据访问技术(例如数据读取器,因为大多数orms将无法在键值对和强类型对象)。

我也不建议在构造函数中为实体(globalsettings)赋予一个键值对,因为它与域do关键字值对与域对象无关,而是在映射器层中实现映射,这是您的存储库或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
}

答案 1 :(得分:0)

我认为没有任何ORM可以映射到Key-Value Pairs。事实上,将DataReader用于此数据可能更有效。无论您获得数据,只需使用配置KVP来构建字典,然后使用Property Pattern进行访问。然后,您可以为您知道所需的属性创建强类型访问器。这将允许您对所了解的属性使用强类型对象,同时仍保持在不更改代码的情况下添加属性的灵活性。