灵活的配置数据存储和访问方案

在软件开发过程中,配置数据的管理是一个不可忽视的环节。配置数据的存储和访问方式直接影响到软件的灵活性和可维护性。在寻找合适的配置管理方案时,发现现有的解决方案并不能满足需求,因此决定开发自己的版本,并在此分享,以期对他人有所帮助。

为了确保这个方案的实用性,设定了几个必须满足的条件:

  • 用户应该能够轻松地更改或选择配置数据的存储方式和位置,而不影响可配置对象。
  • 配置的访问和存储应该对用户来说非常简单和透明,但同时要保证可靠性。
  • 加载配置和子对象的过程不知道任何子对象的类型,子对象的创建依赖于特定的配置。

在进行一个Web项目时,使用了ViewState来存储页面回发之间的一些值,这启发了:字符串可以表示任何数据,包括二进制数据。它们相对容易使用,并且几乎可以存储在任何地方——XML文件、数据库,甚至是二进制文件。就像在XML中操作字符串一样,可以将数据作为字符串访问和存储,并在加载时将其转换为适当的数据类型。

概念定义

为了管理复杂的配置,提出了两个概念:上下文(Context)和值(Value)。上下文是一个容器,包含其他上下文和值的集合;值则是简单的字符串值。加载和保存操作通过两个方法执行,类似于IXmlSerializable接口。

需要实现IConfigurationElement接口,以便类配置可以保存和加载。这个接口类似于IXmlSerializable接口,包括两个方法:ReadConfiguration和WriteConfiguration。顾名思义,一个用于读取配置,另一个用于写入。

public interface IConfigurationElement { void ReadConfiguration(IConfigurationContext context); void WriteConfiguration(IConfigurationContext context); }

由于只处理字符串,可以使用索引器来加载和保存值。用户需要负责在读取时将字符串转换为适当的数据类型,写入时再转换回来。例如:

// 写入 context["DateOfBirth"] = DateOfBirth.ToShortDateString(); // 读取 DateTime dt; DateTime.Parse(context["DateOfBirth"], out dt);

现在,如果想要保存配置值的一个子集,需要通过创建一个新上下文或获取现有上下文来获得一个上下文对象。为此,IConfigurationContext提供了Get、GetAll和Create三个方法。

public interface IConfigurationContext { IEnumerable<IConfigurationContext> Get(string contextName); IEnumerable<IConfigurationContext> GetAll(); string this[string name] { get; set; } string Name { get; } IConfigurationContext Create(string contextName); }

下面是一个访问和存储人名(FirstName和LastName)以及邮寄地址(MailingAddress)的示例。示例中不包括PostalAddress类的实现,但它在附带的源代码中,以及其他未显示的验证逻辑。

public class Person : IConfigurationElement { public string FirstName { get; set; } public string LastName { get; set; } public PostalAddress MailingAddress { get; set; } public void WriteConfiguration(IConfigurationContext context) { context["FirstName"] = FirstName; context["LastName"] = LastName; var ctx = context.CreateContext("MailingAddress"); MailingAddress.WriteConfiguration(ctx); } public void ReadConfiguration(IConfigurationContext context) { FirstName = context["FirstName"]; LastName = context["LastName"]; var ctx = context.GetContext("MailingAddress"); MailingAddress.ReadConfiguration(ctx); } }

现在让看看如何使用它。为此,创建了一个使用XmlNode存储配置的IConfigurationContext的工作实现。因此,下面是一个应该足够简单的示例。

// 加载 static void Main() { var xmlDoc = new XmlDocument(); xmlDoc.Load("FileName"); var context = new XmlConfigurationContext(xmlDoc.DocumentElement); var person = new Person(); person.LoadConfiguration(context); } // 保存 static void Main() { var xmlDoc = new XmlDocument(); var context = new XmlConfigurationContext(xmlDoc, "Person"); person.WriteConfiguration(context); xmlDoc.Save("FileName"); }

下面是创建的配置文件示例:

<Context Name="Person"> <Value Name="FirstName"> FirstName </Value> <Value Name="LastName"> LastName </Value> <Context Name="MailingAddress"> <Value Name="Street1"> Street1 </Value> <Value Name="Street2"> Street2 </Value> <Value Name="City"> City </Value> <Value Name="State"> State </Value> <Value Name="Zip"> Zip </Value> </Context> </Context>
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485