2
\$\begingroup\$

I have been unable to find any other way to update a user config file than the following method.

public class SettingServices : ISettingServices
{
    public UserSetting GetUserSetting()
    {
        XmlSerializer reader = new XmlSerializer(typeof(UserSetting));
        StreamReader file = new StreamReader(UserConfig);
        UserSetting settings = new UserSetting();
        settings = (UserSetting)reader.Deserialize(file);
        return settings;
    }
    public void CreateUserSetting(UserSetting userSetting)
    {
        XmlSerializer writer = new XmlSerializer(typeof(UserSetting));
        StreamWriter file = new StreamWriter(UserConfig);
        writer.Serialize(file, userSetting);
        file.Close();
    }
    public void UpdateUserSetting(UserSetting userSetting)
    {
        UserSetting currentSettings = GetUserSetting();
        UserSetting newSetting = new UserSetting();
        newSetting.Name = (userSetting.Name == null) ? currentSettings.Name : userSetting.Name;
        newSetting.ViewChangeLog = (userSetting.ViewChangeLog == null) ? currentSettings.ViewChangeLog : userSetting.ViewChangeLog;
        newSetting.PrimaryRowColor = (userSetting.PrimaryRowColor == null) ? currentSettings.PrimaryRowColor : userSetting.PrimaryRowColor;
        newSetting.SecondaryRowColor = (userSetting.SecondaryRowColor == null) ? currentSettings.SecondaryRowColor : userSetting.SecondaryRowColor;
        newSetting.Font = (userSetting.Font == null) ? currentSettings.Font : userSetting.Font;
        CreateUserSetting(newSetting);
    }
    private static string UserConfig
    {
        get
        {
            string configDirectory = new Uri(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\CVS\\ICMQuery").LocalPath;
            return new Uri(configDirectory + "\\" + System.Environment.UserName + ".config").LocalPath;
        }
    }
}

Can someone please show me the light. I would preferably like to be able to update singular elements within the UserSetting class without destroying and rewriting the file every time I have to update it.

\$\endgroup\$
  • \$\begingroup\$ What are you trying to achieve? Why do you want to update the file? \$\endgroup\$ – DerApe Jul 9 '14 at 5:45
  • \$\begingroup\$ @derape this xml file is storing user settings for a winforms app. So lets say the user decides he/she wants to change their PrimaryRowColor (One of the alternating row colors for DataGridViews) setting from red to blue. Preferably I'd like to just be able to update that node in the XML file without having to rewrite the whole file every time a change is made. \$\endgroup\$ – aaronmallen Jul 9 '14 at 13:50
  • \$\begingroup\$ I got that, but what is the reason you don't want to write the whole file? \$\endgroup\$ – DerApe Jul 9 '14 at 13:53
  • \$\begingroup\$ @derape I don't want to REWRITE the whole file. This file is already written when the user uses the app for the first time. It seems to me it would be inefficient to rewrite the file everytime a change is made, what if this XML file contained 10,000 different nodes... There has to be a way to update it instead of rewritting the whole file right? \$\endgroup\$ – aaronmallen Jul 9 '14 at 13:57
  • \$\begingroup\$ Correct, but then you can not use the serializer, because that's the whole point of a serializer: to consistently serialize an object! If you want to update those nodes seperately you would have to open the xml yourself (append mode), navigate to your nodes, change them, and save it back... \$\endgroup\$ – DerApe Jul 9 '14 at 14:01
1
\$\begingroup\$

Preferably I'd like to just be able to update that node in the XML file without having to rewrite the whole file every time a change is made.

In general, that's simply not possible, because XML is a text-based format.

Imagine you have the following file:

<UserSettings>
    <Name>Aron</Name>
    <!-- other settings here -->
</UserSettings>

Now you want to fix the name from “Aron” to “Aaron”:

<UserSettings>
    <Name>Aaron</Name>
    <!-- other settings here -->
</UserSettings>

But doing this means that everything that's after the Name line has to be moved by one byte in the file, so almost the whole file has to be rewritten.

With config files, this usually doesn't matter, because they tend to be relatively small. If it does matter to you, you will have to use another way of saving the config; a good choice might be an embedded database, like SQL Server Compact or SQLite.

Yet another option would be to use .settings files (built-in in VS). It doesn't save you from rewriting the file, but it saves you from having to write all that code.

\$\endgroup\$
  • \$\begingroup\$ Thanks I figured that out and everything I figured out is what you just said so marking as answered. Side note: went with JSON for everything I didn't want in the settings file. \$\endgroup\$ – aaronmallen Jul 16 '14 at 14:09
1
\$\begingroup\$

Employ the using construct to deterministically dispose of your objects which implement the IDisposable interface (also, you're creating a new UserSetting() object that is immediately discarded by the deserialization on the next line):

public UserSetting GetUserSetting()
{
    XmlSerializer reader = new XmlSerializer(typeof(UserSetting));
    using (StreamReader file = new StreamReader(UserConfig))
    {
        return (UserSetting)reader.Deserialize(file);
    }
}

public void CreateUserSetting(UserSetting userSetting)
{
    XmlSerializer writer = new XmlSerializer(typeof(UserSetting));
    using (StreamWriter file = new StreamWriter(UserConfig))
    {
        writer.Serialize(file, userSetting);
    }
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.