I'm writing a game server in C# and would like to reload or refresh settings from a config file while the server is running.
Ideally I would like to save the settings in an XML file, have the ability to edit
the file while the game server is running and then send the server the command to reload
the settings from the file.
I know I can use a database to do this as well, but the game server is fairly small and I think it would be more practical to just save settings in a flat-file. I will have file-level access to the machine the server will run on.
What should I use?
Use http://msdn.microsoft.com/en-us/library/system.configuration.configurationmanager.aspx
Use a Custom Configuration Section, hookup the sections from the app.config to external config file(s) by setting the location attrib of the section. All xml loading and serialization is done by those custom classes
Code provided by CarelZA:
First of all, ConfigurationManager caches the application's configuration by config section, and you can call ConfigurationManager.RefreshSection() to invalidate the cache for a specific section.
In app.config I added:
<configSections>
<section name="gameSettings"
type="System.Configuration.NameValueSectionHandler,system , Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, Custom=null"/>
</configSections>
<gameSettings configSource="game.config"/>
I created a file called "game.config" and set "Copy to Output Directory" to "Copy always".
In game.config:
<gameSettings>
<add key="SettingName" value="SettingValue" />
</gameSettings>
Then in code, in order to access any setting:
settings = (NameValueCollection) ConfigurationManager.GetSection("gameSettings");
return settings["SettingName"];
And to reload the game config at any time when the reload command is sent to the server:
ConfigurationManager.RefreshSection("gameSettings");
As per request posting my comment as an answer:
You can set it up so the server auto-loads the file settings with FileSystemWatcher. If you use a custom Settings
class, you can simply lock the class, reload it from a file and unlock it (if you are using multiple threads).
Reading/writing from/to file or serialization is so trivial in .NET that that is probably not what you need help with and there are many options how to do it.
Sounds like a job for XML Serialization! Instead of manually parsing and editing XML, you can easily achieve this same effect by creating a settings object, serializing it to XML, and de/serializing it when you need to make modifications. This way, you could hot swap configuration files.
using System.Xml.Serialization;
For instance, you could have the object
public class Settings
{
public string SomeProperty {get; set;}
public string SomeProperty2 {get; set;}
}
Save it to your disk as,
var settings = new Settings {SomeProperty="Hello", SomeProperty2="Joe"};
var fs = new FileStream("settings.xml");
var xs = new XmlSerializer(settings.GetType());
xs.Serialize(fs,settings);
Read it back in as,
var fs = new FileStream("settings.xml");
var settings = (Settings)fs.Deserialize(fs);
Check out the MemoryCache in System.Runtime.Caching (.NET 4.0). You could write yourself a simple class which performs the following steps:
- Load the XML file
- Parse its contents into whatever representation you want them in
- Store the output in the cache with a HostFileChangeMonitor watching it - this will cause it to be removed from the cache automatically when the file is changed
Before performing any of the above, you'd check the cache to see if a previously-cached copy of the settings exists and only proceed if it doesn't.
The advantage of rolling your own approach like this is that you do not trigger restarts of the application as is the case with AppSettings stored in your web.config or app.config files. (It should be said that this is not the only way of achieving this)