ConfigurationManager可以在Save()上保留XML注释吗?

时间:2009-12-23 17:58:31

标签: c# xml configuration-files xml-comments configurationmanager

我编写了一个小实用程序,允许我为另一个应用程序的App.config文件更改一个简单的AppSetting,然后保存更改:

 //save a backup copy first.
 var cfg = ConfigurationManager.OpenExeConfiguration(pathToExeFile);
 cfg.SaveAs(cfg.FilePath + "." + DateTime.Now.ToFileTime() + ".bak"); 

 //reopen the original config again and update it.
 cfg = ConfigurationManager.OpenExeConfiguration(pathToExeFile);
 var setting = cfg.AppSettings.Settings[keyName];
 setting.Value = newValue;

 //save the changed configuration.
 cfg.Save(ConfigurationSaveMode.Full); 

除了一个副作用外,这种方法效果很好。 新保存的.config文件会丢失所有原始XML注释,但仅在AppSettings区域内。是否可以从原始配置文件AppSettings区域保留XML注释?

Here's a pastebin of the full source if you'd like to quickly compile and run it.

3 个答案:

答案 0 :(得分:27)

我跳进了Reflector.Net并查看了这个类的反编译源代码。简短的回答是否定的,它不会保留评论。 Microsoft编写该类的方法是从配置类的属性生成XML文档。由于注释没有出现在配置类中,因此它们不会将其返回到XML中。

更糟糕的是,Microsoft密封了所有这些类,因此您无法派生新类并插入自己的实现。您唯一的选择是将评论移到AppSettings部分之外,或使用XmlDocumentXDocument类来解析配置文件。

对不起。这是微软刚刚没有计划的边缘案例。

答案 1 :(得分:4)

以下是可用于保存注释的示例函数。它允许您一次编辑一个键/值对。我还添加了一些东西来根据我通常使用文件的方式很好地格式化文件(如果你愿意,你可以轻松删除它)。我希望将来可以帮助其他人。

public static bool setConfigValue(Configuration config, string key, string val, out string errorMsg) {
    try {
        errorMsg = null;
        string filename = config.FilePath;

        //Load the config file as an XDocument
        XDocument document = XDocument.Load(filename, LoadOptions.PreserveWhitespace);
        if(document.Root == null) {
            errorMsg = "Document was null for XDocument load.";
            return false;
        }
        XElement appSettings = document.Root.Element("appSettings");
        if(appSettings == null) {
            appSettings = new XElement("appSettings");
            document.Root.Add(appSettings);
        }
        XElement appSetting = appSettings.Elements("add").FirstOrDefault(x => x.Attribute("key").Value == key);
        if (appSetting == null) {
            //Create the new appSetting
            appSettings.Add(new XElement("add", new XAttribute("key", key), new XAttribute("value", val)));
        }
        else {
            //Update the current appSetting
            appSetting.Attribute("value").Value = val;
        }


        //Format the appSetting section
        XNode lastElement = null;
        foreach(var elm in appSettings.DescendantNodes()) {
            if(elm.NodeType == System.Xml.XmlNodeType.Text) {
                if(lastElement?.NodeType == System.Xml.XmlNodeType.Element && elm.NextNode?.NodeType == System.Xml.XmlNodeType.Comment) {
                    //Any time the last node was an element and the next is a comment add two new lines.
                    ((XText)elm).Value = "\n\n\t\t";
                }
                else {
                    ((XText)elm).Value = "\n\t\t";
                }
            }
            lastElement = elm;
        }

        //Make sure the end tag for appSettings is on a new line.
        var lastNode = appSettings.DescendantNodes().Last();
        if (lastNode.NodeType == System.Xml.XmlNodeType.Text) {
            ((XText)lastNode).Value = "\n\t";
        }
        else {
            appSettings.Add(new XText("\n\t"));
        }

        //Save the changes to the config file.
        document.Save(filename, SaveOptions.DisableFormatting);
        return true;
    }
    catch (Exception ex) {
        errorMsg = "There was an exception while trying to update the config value for '" + key + "' with value '" + val + "' : " + ex.ToString();
        return false;
    }
}

答案 2 :(得分:2)

如果评论很重要,可能只是您唯一的选择是阅读&手动保存文件(通过XmlDocument或新的Linq相关API)。然而,如果这些评论并不重要,我会让他们放弃或考虑将它们嵌入(尽管是多余的)数据元素。