自动生成用于访问xml文件的代码的工具

时间:2010-05-04 12:44:02

标签: c# xml

我的应用程序有一个配置xml文件。该文件包含50多个程序设置。目前,我分别阅读并保存每个程序设置。我猜这样的任务没有效率

我需要能够自动生成加载代码的东西,并使用预定义的xml-schema保存我的程序设置。

我在添加新项对话框中找到了一个数据集。不幸的是,由于这个

,我无法向dataset1添加新代码,例如属性的set-accessors中的事件
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.

也许,有一个工具允许用户生成一个用于访问xml文件的包装器?例如DataSet1,但具有添加事件的可用性。

编辑:我没有标记有用的答案,因为我读了你给我的文章(链接)。我稍后会标出有用的答案。

8 个答案:

答案 0 :(得分:2)

如果您的xml文件有适当的xsd架构,则microsoft提供 xsd.exe ,这是一个为此架构自动生成c#类的小工具。

有关详细信息,请参阅:http://msdn.microsoft.com/en-us/library/x6c1kb0s%28VS.71%29.aspx

答案 1 :(得分:2)

如果你不愿意使用app.config / web.config或属性文件(Oded和Bruno推荐我也推荐),我强烈推荐这个实用程序:

VS2008和VS2010

Web Services Contract First (WSCF) Blue

如果您使用的是VS2005,则需要使用此版本的工具:http://www.thinktecture.com/resourcearchive/tools-and-software/wscf(请勿在此网站上使用VS2008版本。我永远无法使其正常工作。)

将插件安装到Visual Studio后,您将需要XML文件的XSD架构。 (Google for an online XSD Generator。)按照WSCF网站上的说明,您可以生成一个包装类,它将对XML进行反序列化和重新序列化,并为您提供XML的抽象视图。

我认为添加新节点/元素TYPES是不可能的(或者至少很难),但是添加现有节点/元素类型的新实例,访问数据,编辑数据,重新排序节点,然后保存回来出去都很容易。

反序列化代码如下所示:

private MyGeneratedXMLconfigClass config;
using (StreamReader sr = new StreamReader(filename))
{
   XmlSerializer cXml = new XmlSerializer(typeof(MyGeneratedXMLconfigClass));
   config = (MyGeneratedXMLconfigClass)cXml.Deserialize(sr);
}

现在您的XML已反序列化到自定义类的“config”实例中。然后,您可以将整个类作为一系列嵌套值和列表访问。

例如:

string errorFile = config.errorsFile;
List<string> actions = config.actionList;
var specialActions = from action in config.actionList
                      where action.contains("special")
                      select action;

等等。然后,一旦完成操作数据,就可以使用以下代码重新序列化:

using (StreamWriter wr = new StreamWriter(filename, false))
{
   XmlSerializer cXml = new XmlSerializer(typeof(MyGeneratedXMLconfigClass));
   cXml.Serialize(wr, config);
}

这个工具的一个非常好的事情是它自动生成所有类作为“部分”类,这样你就可以自己扩展每个类,而不用担心你的代码被踩到了以防你因为XSD / XML已经改变,所以需要重新生成。

我想这可能听起来很多,但学习曲线实际上非常简单,一旦你安装并正常工作,你就会意识到它是多么愚蠢。这很值得。我发誓。 : - )

答案 2 :(得分:1)

为什么使用手动XML进行配置?现有的app.configweb.config架构有什么问题?

答案 3 :(得分:1)

为什么不使用.Settings file

答案 4 :(得分:1)

您可以按照以下步骤操作:

1)从XML文件生成XSD文件。因为曾经有一个从XML文件推断模式的工具,我忘了它的名字。目前我使用自己的实用程序,它基本上运行此核心例程来读取xml文件并生成相应的xsd:

static void InferSchema(string fileName)
{
    XmlWriter writer = null;
    XmlSchemaInference infer = new XmlSchemaInference();
    XmlSchemaSet sc = new XmlSchemaSet();

    string outputXsd = fileName.Replace(".xml", ".xsd");
    sc = infer.InferSchema(new XmlTextReader(fileName));

    using (writer = XmlWriter.Create(new StreamWriter(outputXsd)))   
    {
        foreach(XmlSchema schema in sc.Schemas())
        {
            schema.Write(writer);
            Console.WriteLine(">> found schema - generated to {0}", 
            outputXsd);
        }
    }
}

2)运行xsd.exe以从XSD文件生成可序列化的类。

xsd.exe /c /n:MyNameSpaceHere MyGenerated.xsd

接下来,您可以使用XmlSerializer.Serialize()方法将XML文件读入可序列化类。像这样:

    public static void Serialize<T>(T data, TextWriter writer)
    {
        try
        {
            XmlSerializer xs = new XmlSerializer(typeof(T));
            xs.Serialize(writer, data);
        }
        catch (Exception e)
        {
            throw;
        }
    }

最后,您可以使用XmlSerializer.Deserialize()方法从类中回写XML文件,例如:

public static void Deserialize<T>(out T data, XmlReader reader)
{
    try
    {
        XmlSerializer xs = new XmlSerializer(typeof(T));
        data = (T)xs.Deserialize(reader);
    }
    catch (Exception e)
    {
        reader.Close();
        throw;
    }
}

答案 5 :(得分:0)

这称为属性文件。 C#应该类似于Java的Properties类,您可以在其中加载所有属性而无需对其名称进行硬编码。

编辑: 显然没有针对C#的内置属性解析解决方案。但是你可以轻松实现自己的。请参阅here

答案 6 :(得分:0)

如果您有XSD文件,则可以从中生成类。除了已经提到过的微软的xsd.exe(它已经有很长时间没有更新),还有其他工具可供选择。我正在使用XSD2Code,它允许生成强类型集合,延迟初始化等等。

如果您没有XSD,可以将xsd.exe指向xml文件,它将从中生成XSD。模式通常需要一些工作,但通常是一个很好的起点。

xsd.exe (instance).xml

答案 7 :(得分:0)

您可以使用System.Xml.Serialization - 它非常简单,您可以直接序列化类对象,例如MyCustomClass(它甚至可以保存MyCustomClass公共字段)。

反序列化XML文件将获得MyCustomClass的新实例,因此这样的功能是无价的。

注意一件事:你应该添加你在课堂上使用的每种单一类型,但这很容易。

我附上了一个完整的项目,可以完成您想要的任务。只需更改类和对象即可。 source code

例如

(我正在缩短代码):

using System.Xml;
using System.Xml.Serialization;
using System.IO;

[XmlRootAttribute("Vendor")]
class Vendor{
    [XmlAttribute]
    Product prod;
}
[XmlRootAttribute("Product")]
class Product{
    [XmlAttribute]
    public string name="";
}

class Test{
    Vendor v=new Vendor();
    Product p=new Product();
    p.name="a cake";
    v.prod=p;

    //add EVERY SINGLE TYPE you use in the serialized class.
    Type[] type_list = { typeof(Product) };

        XmlSerializer packer = new XmlSerializer(v.GetType(),type_list);
        XmlWriter flusher = XmlWriter.Create(@"c:\bak.xml");




        packer.Serialize(flusher, v);

        flusher.Close();

        XmlReader restorer = XmlReader.Create(@"c:\bak.xml");
        Vendor v2 = (Vendor)packer.Deserialize(restorer);

    //v2.prod.name is now "cake"
    //COOL was my first impression :P

}