c#:使用Assemblies(via Reflection)作为(meta)数据存储

时间:2010-01-26 06:19:20

标签: c# xml reflection assemblies metadata

一些背景

  • 我的一个项目需要携带一些“元数据”(是的,我讨厌使用这个词)。
  • 元数据具体包含的内容并不重要,只是它比简单的“表格”或“列表”更复杂 - 您可以将其视为信息的迷你数据库
  • 目前,我将此元数据存储在XML文件中,并具有定义架构的XSD。
  • 我想将此元数据打包到我的项目中,目前这意味着将XML文件保留为资源
  • 但是,我一直在寻找更多强类型替代品。我正在考虑将它从XML文件转移到C#代码 - 所以不要使用XML apis来遍历我的元数据,而是通过类型反射来依赖.NET代码
  • 除了强(er)类型之外,我从使用程序集看到的一些有用的特性是这样的:(1)我可以使用像Resharper这样的工具在某种程度上重构“模式”,(2)元数据可以随附代码,(3)不必依赖任何外部数据库组件。

问题

  • 如果你尝试过类似的东西,我很好奇你所学到的东西。
  • 您的体验是否积极?
  • 你学到了什么?
  • 你发现了这种方法有哪些问题?
  • 我应该考虑哪些因素?
  • 你会再这样做吗?

注意

  • 我不是要求如何使用反射 - 那里不需要帮助
  • 从根本上询问您的经验和设计注意事项

更新:关于元数据的信息

因为有人问我会尝试更多地描述元数据。我试图抽象一点 - 所以这看起来有点人为。

模型中有三个实体:

  • 一组“组” - 每个组都有一个唯一的名称和几个属性(通常是表示某种ID号的int值)
  • 每个“组”包含一个或多个“小部件”(从不超过50个) - 每个项目都有名称(有多个名称),ID和各种布尔属性等属性。
  • 每个小部件包含一个或多个“方案”。每个“场景”都是文档 - 指向如何使用窗口小部件的描述的URL。

通常我需要运行这些类型的“查询”

  • 获取所有小部件的名称
  • 获取包含至少一个小部件的所有组的名称,其中BoolProp1 = true
  • 获取窗口小部件的ID,该组包含该窗口小部件

我如何考虑对程序集中的实体进行建模

  • 共有3个类:Group,Widget,Documentation
  • 有25个组,所以我将有25个Group类 - 所以“FooGroup”将派生自Group,小部件和文档的格式如下
  • 每个类都有属性来说明名称,ID等。

2 个答案:

答案 0 :(得分:1)

从您的描述中不清楚,但听起来您希望能够访问的程序集级元数据(而不是类型级别)。您可以在每个程序集中有一个实现公共接口的类,然后使用反射来搜索该类并实例化它。然后,您可以在其中对元数据进行硬编码。

问题当然是你从XML中失去的好处 - 即你没有新的构建就无法修改元数据。但如果你正朝着这个方向前进,你可能已经考虑到了这一点。

答案 1 :(得分:1)

我已经为我的大部分项目使用和扩展了元数据,其中许多与描述组件,它们之间的关系,映射等有关。

(主要使用属性类别包括O / R Mappers,依赖注入框架和序列化描述 - 特别是XML序列化)

好吧,我将要求您详细描述要嵌入资源的数据的性质。使用属性自然适用于描述类型和类型元素的数据类型,但属性的每种用法都是简单而短的。属性(我认为)应该非常有凝聚力并且彼此独立。

我想指出的一个解决方案是“XML序列化”方法。您可以保留当前的XML,并将它们作为嵌入式资源(这是您可能已经完成的工作)放入程序集中,并立即将整个XML读入强类型的对象层次结构中。

在我看来,XML序列化使用起来非常简单,比典型的XML API甚至LINQ2XML简单得多。它使用Attributes将类属性映射到XML元素和XML属性。一旦将XML加载到对象中,就可以将内存中所需的全部内容称为“类型化”数据。

根据我对你的描述的理解,我认为你有很多数据要放在一个类上。这意味着一个庞大的(在我看来)丑陋的属性代码在类之上。 (除非您可以在成员之间分发您的数据,使每个成员都小而独立,这很好。)

我有很多使用XML序列化来处理大量数据的积极经验。您可以根据需要排列数据,获得类型安全性,获得IntelliSence(如果您将XSD提供给visual studio),并且您也可以获得一半的重构。 ReSharper(或我所知的任何其他重构工具)无法识别XML序列化,因此当您重构类型化的类时,它不会更改XML本身,但会更改数据的所有使用。

如果您向我提供有关您的数据的更多详细信息,我可以在我的答案中添加一些内容。

对于XML序列化示例,只需Google“XML序列化”或在MSDN中查找。

更新

我强烈建议 NOT 使用类来表示数据实例。或者甚至使用来封装数据是违反其逻辑定义的。

我猜你最好的选择是XML序列化,只要你已经拥有XML数据。使用更少的代码,您可以获得所需的所有好处。您可以使用LINQ2Objects对XML Serializable对象执行任何查询。

您的代码的一部分可能如下所示:

[XmlRoot]
public class MyMetadata
{

    [XmlElement]
    public Group[] Groups { get; set; }

}

public class Group
{

    [XmlAttribute]
    public string Name { get; set; }

    [XmlAttribute]
    public int SomeNumber { get; set; }

    [XmlElement]
    public Widget[] Widgets { get; set; }

}

public class Widget
{
    ...
}

您应该调用new XmlSerializer(typeof(MyMetadata))来创建序列化程序,并调用其Deserialize方法为其提供XML流,然后您将获得一个MyMetadata类的填充实例。