سؤال

لقد كتبت أداة صغيرة تتيح لي تغيير مجموعة تطبيقات بسيطة لملف تطبيق تطبيق آخر ، ثم حفظ التغييرات:

 //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. هل من الممكن الاحتفاظ بتعليقات XML من منطقة تطبيقات ملفات التكوين الأصلية؟

إليك عبارة عن Pastebin للمصدر الكامل إذا كنت ترغب في تجميعه بسرعة وتشغيله.

هل كانت مفيدة؟

المحلول

لقد قفزت إلى Reflector.net ونظرت إلى المصدر الذي تم حلها لهذه الفئة. الجواب المختصر هو لا ، لن يحتفظ بالتعليقات. الطريقة التي كتبت بها Microsoft الفئة هي إنشاء مستند XML من الخصائص في فئة التكوين. نظرًا لأن التعليقات لا تظهر في فئة التكوين ، فإنها لا تعيدها إلى XML.

وما الذي يجعل هذا الأمر أسوأ هو أن Microsoft قامت بإغلاق كل هذه الفئات ، لذا لا يمكنك استخلاص فئة جديدة وإدراج تطبيقك الخاص. خيارك الوحيد هو نقل التعليقات خارج قسم Appsettings أو الاستخدام XmlDocument أو XDocument الفصول لتحليل ملفات التكوين بدلاً من ذلك.

آسف. هذه حالة حافة لم تخطط Microsoft لها.

نصائح أخرى

فيما يلي وظيفة عينة يمكنك استخدامها لحفظ التعليقات. يتيح لك تحرير زوج مفتاح/قيمة واحد في وقت واحد. لقد أضفت أيضًا بعض الأشياء لتنسيق الملف بشكل جيد بناءً على الطريقة التي أستخدم بها الملفات بشكل شائع (يمكنك بسهولة إزالة ذلك إذا كنت تريد). آمل أن يساعد هذا شخصًا آخر في المستقبل.

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;
    }
}

إذا كانت التعليقات حاسمة ، فقد يكون الخيار الوحيد هو قراءة الملف وحفظه يدويًا (عبر XmlDocument أو واجهة برمجة التطبيقات الجديدة ذات الصلة LINQ). ومع ذلك ، إذا لم تكن هذه التعليقات حرجة ، فسأسمح لهم إما بالرحيل أو ربما أفكر في تضمينها كعناصر بيانات (وإن كانت زائدة).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top