有一个电子文件管理系统。数据交换是使用具有以下结构的 XML 完成的:
<document>
<tag1 value="1"/>
<tag2 value="text"/>
<tag3 value="01.01.2017 10:20:15"/>
<tag4 value="2"/>
<tag5 value="02.02.2017 20:30:45"/>
<tag6 value="text too"/>
<tag7 value="3.5"/>
<outerTag1>
<innerTag11 value="5"/>
<innerTag12 value="some text"/>
<innerTag13 value="some text"/>
<innerTag14 value="7"/>
<innerTag15 value="8"/>
<innerTag16 value="6"/>
<innerOuterTag11>
<innerInnerTag111 value="text"/>
<innerInnerTag112 value="03.03.2017 03:03:03"/>
</innerOuterTag11>
</outerTag1>
<outerTag2>
<innerTag21 value="text"/>
<innerTag22 value="text"/>
<innerTag23 value="text"/>
<innerTag24 value="text"/>
<innerTag25 value="text"/>
<innerTag26 value="text"/>
</outerTag2>
</document>
问题就在眼前——你需要一堆具有这种结构的类:
[XmlRoot(ElementName="tag1")]
public class Tag1
{
[XmlAttribute(AttributeName="value")]
public int Value { get; set; }
}
接着:
[XmlRoot(ElementName="document")]
public class Document
{
[XmlElement(ElementName="tag1")]
public Tag1 Tag1 { get; set; }
[XmlElement(ElementName="tag2")]
public Tag2 Tag2 { get; set; }
[XmlElement(ElementName="tag3")]
public Tag3 Tag3 { get; set; }
[XmlElement(ElementName="tag4")]
public Tag4 Tag4 { get; set; }
[XmlElement(ElementName="tag5")]
public Tag5 Tag5 { get; set; }
[XmlElement(ElementName="tag6")]
public Tag6 Tag6 { get; set; }
[XmlElement(ElementName="tag7")]
public Tag7 Tag7 { get; set; }
[XmlElement(ElementName="outerTag1")]
public OuterTag1 OuterTag1 { get; set; }
[XmlElement(ElementName="outerTag2")]
public OuterTag2 OuterTag2 { get; set; }
}
我想改为编写一个具有简单类型属性的类:
[XmlRoot(ElementName="document")]
public class Document
{
[...(ElementName="tag1")]
public int Tag1 { get; set; }
[...(ElementName="tag2")]
public string Tag2 { get; set; }
[...(ElementName="tag3")]
public DateTime Tag3 { get; set; }
[...(ElementName="tag4")]
public int Tag4 { get; set; }
[...(ElementName="tag5")]
public DateTime Tag5 { get; set; }
[...(ElementName="tag6")]
public string Tag6 { get; set; }
[...(ElementName="tag7")]
public decimal Tag7 { get; set; }
[XmlElement(ElementName="outerTag1")]
public OuterTag1 OuterTag1 { get; set; }
[XmlElement(ElementName="outerTag2")]
public OuterTag2 OuterTag2 { get; set; }
}
而不是产生一堆像Tag1
, Tag2
, ...这样的小类
这可以以某种方式完成吗?理想情况下,我想制作一个自定义属性MyXmlElement
并使用它来代替XmlElement
,但是如何教XmlSerializer
理解它并生成相应的标记?或者也许还有其他方法?
让我们进行代码生成,好吗?T4很棒。我们将创建两个类,一个具有用于序列化的嵌套类,另一个是平面且易于使用的。和转换功能。
我们将基于这样的XML 文档生成(我把它放在一个名为DocumentProto.xml 的项目中)。
我们通过 Add New Item → Text Template(不是 Runtime TextTemplate!)将新的 T4 类型文件放入项目中。我将其命名为 Document.tt。
在第一行中,更改
hostspecific="false"
为true
。添加必要的程序集:和
更改
output extension
为".cs"
.接下来是技术问题:我们需要解析 XML。打开文档,将其读入内存:
创建文件模板:
现在,生成一组用于序列化的类。我们在 tt 文件的末尾写(之前在命令行测试应用程序上对此进行了调试):
(标签
<#+ #>
内有额外的生成方法。)我们用:
我们进入 Document.cs:
我们还将“平面类”属性的生成添加到文件末尾:
和一个属性读取器方法到一个平面类中:
我们在上面使用它们:
我们得到一组现成的生成类供使用:
更新:更正
GenerateNestedClasses
此:在
GenerateFlatteningBody
最后一行我们得到了表格的中间类
以防万一,tt模板的完整代码和生成的结果:https ://gist.github.com/vladd/7f25e0ceb625372bffdbf9b455452ae1
我拒绝实现接口
IXmlSerializable
- 解决方案结果非常繁琐且不美观,此外,您需要考虑在序列化程序的正常操作中考虑到的许多细微差别。结果,我写了一个简单的类:
这让我们可以扔掉一堆小班
Tag1
,Tag2
等等。文档本身如下所示:好吧,感谢隐式类型转换的运算符,创建文档同样简单: