我遇到了一个两难的问题。我的C#应用程序使用一种自定义文件格式,需要在文本编辑器中可供人类编辑,但也可以通过应用程序中的图形用户界面进行编辑。这个文件将表示一个顶级对象(称为TopObject),它包含几个较小的对象,而这些对象又包含其他对象,依此类推。这些对象中包含的所有数据都在文件中提供。
我陷入了如何加载/保存这些文件的问题。C#序列化不适合我,因为它破坏了人工可编辑性(二进制序列化),或者在序列化基类集合时有“问题”(XML和DataContract序列化,它们在序列化基类时添加文本来消除派生类的歧义,这使得文件更容易被人类编辑);如果不是因为需要手动编辑文件,它就是门票。我一直在研究诸如GOLD和GPLEX/GPPG这样的解析器生成器来解析文件并将其转换为它们所表示的对象,这看起来很有希望,但这只涵盖了加载文件的一个方向,并不能确保在写出文件时将它们保存为正确的格式。
最好的方法是指定一种同时处理以下两种情况的语法:
1)读取具有指定结构的文件,并将其转换为TopObject及其包含的所有对象,以及
2)给定一个TopObject,将其状态写到具有相同结构的文件中。
在很大程度上,只需要一个语法就可以实现导入结构和输出结构。
有没有这样的工具或框架可以帮助我?这是可行的吗,还是我想太多了,有一种更简单的方法?
发布于 2011-02-03 10:06:36
我仍然会使用XML,但只需编写您自己的序列化程序。您可以使用.Net中的XML读取器/写入器类来创建一个简单的XML格式:
<TopObject>
<SubObject>
<SubObject>
etc.
</SubObject>
<SubObject>
etc.
</SubObject>
</SubObject>
<SubObject></SubObject>
</TopObject>我不知道您是否认为这足够人类可读,但最好是.Net序列化程序创建的东西。以递归方式读/写将非常简单。
示例:
这里有一个您可以适应的简单示例。假设我有这样的类:
public class Node {
public Node(String _SomeProperty) {
this.SomeProperty = _SomeProperty;
}
public String SomeProperty;
public List<Node> Children = new List<Node>();
}每个Node都有一个称为SomeProperty的属性。它也可以有孩子;在Children属性中有更多的Nodes。
下面是一个控制台应用程序的main,它从这个类中创建一些数据进行序列化:
static void Main(string[] args) {
// Make some data for testing
Node baseObject = new Node("This is the base class");
List<Node> Children = new List<Node>(){
new Node("This is a child"),
new Node("This is another child")
};
baseObject.Children = Children;
Node aSubChild = new Node("This is a child of a child");
baseObject.Children[0].Children = new List<Node>() { aSubChild };
// Serialize
XmlWriter writer = XmlWriter.Create("test.xml");
writer.WriteStartDocument();
RecursivelySerialize(ref writer, baseObject);
writer.Flush();
}它调用一个名为RecursivelySerialize的方法,该方法执行实际的工作:
private static void RecursivelySerialize(ref XmlWriter writer, Node sc) {
writer.WriteStartElement("Node");
writer.WriteElementString("SomeProperty", sc.SomeProperty);
if (sc.Children.Count > 0) {
writer.WriteStartElement("Nodes");
foreach (Node scChild in sc.Children)
RecursivelySerialize(ref writer, scChild);
writer.WriteEndElement();
}
writer.WriteEndElement();
}这个方法并不复杂。为了改进它,您可以使用反射来动态序列化任何类型的类。下面是我在运行上面的代码时得到的输出(格式很好):
<?xml version="1.0" encoding="utf-8"?>
<Node>
<SomeProperty>This is the base class</SomeProperty>
<Nodes>
<Node>
<SomeProperty>This is a child</SomeProperty>
<Nodes>
<Node>
<SomeProperty>This is a child of a child</SomeProperty>
</Node>
</Nodes>
</Node>
<Node>
<SomeProperty>This is another child</SomeProperty>
</Node>
</Nodes>
</Node>发布于 2011-02-04 08:38:52
就我个人而言,我不会花太多时间让文件可供人类编辑,至少不能由非技术人员编辑。如果应用程序需要使用文件,那么它将需要准确性,并且无论您建立哪种语法,人类仍然会犯错误。
XML/JSON/INIs对于一些技术人员来说仍然很难不搞砸(令人惊讶),但至少对一些技术人员来说它们是熟悉的。我认为这些都是比滚动你自己的语法更好的选择。更好的是,如果你想让编辑文件变得更加用户友好,你可以考虑放弃“人类可编辑”的要求,使其只能由应用程序编辑。
https://stackoverflow.com/questions/4881983
复制相似问题