Alternative to XML Serialization for Configuration
Currently, we use a giant configuration object that is serialized to/from XML. This has worked fine for the most part, but we are finding that in the case of power loss and application crashes, that the file could be left in a state that renders it unable to deserialize properly, effectively corrupting the configuration information.
I would like to use the built-in app.config, but it doesn't seem to easily support custom classes. For example, with XML serialization, I can easily serialize a generic list<ComplexClass>
with no extra code. It just works. It seems that when using app.config, you have to provide a ton of information and custom classes for this to work. Plus, most of the "custom configuration" tutorials are from circa-2007 and may be outdated for all I know. Does anyone have information to the latest way to do this in .NET 4.0?
In开发者_Go百科 addition, when a problem occurs in the application, 9/10 times it is because of an improper configuration. App.config likes to store user-changeable settings in a very inaccessible location for users who aren't familiar with hidden directories and such. Is there any way to have a single location to store the config file, which the user can easily email us when a problem occurs?
Or, is all this easier than I remember it being in early 2.0 days? Any links or quick examples of how to easily do custom app.config information would be great.
As a further example, this is a pared-down version of one of the types of objects I want to serialize as List<Alarm>
, as the amount of Alarm
s can vary or be empty. Is there an analogous way to store something like this in app.config?
[Serializable]
public class Alarm
{
[Serializable]
public class AlarmSetting
{
public enum AlarmVariables { Concentration, RSquared }
public enum AlarmComparisons { LessThan, GreaterThan }
[Description("Which entity is being alarmed on.")]
public AlarmVariables Variable { get; set; }
[Description("Method of comparing the entity to the setpoint.")]
public AlarmComparisons Comparator { get; set; }
[Description("Value at which to alarm.")]
public Double Setpoint { get; set; }
}
public String Name { get; set; }
public Boolean Enabled { get; set; }
public String Parameter { get; set; }
public List<AlarmSetting> AlarmSettings { get; set; }
public System.Drawing.Color RowColor { get; set; }
}
I would suggest moving away from any sort of config file and instead use some type of local database such as sqlite or sql server express which is much more resilient to app crashes.
IMHO, config settings shouldn't be a default container for user settings. To me a config file is there to make sure the app runs in the given environment. For example, defining connection strings or polling rates or things of that nature.
User settings, especially ones that change often, need a better storage mechanism such as a local database. Unless, of course, it's a client/server application. In which case those settings should be up at the server itself and only persisted locally if the app has to work in a disconnected state.
The example you gave, one of configuring what appears to be one or more alarms is a perfect example of something that belongs in a database table.
I have been using XML serialization, similar to what you are describing, for many years on a number of different projects. Unless you want to bite off SQL for configuration, this seems to be the best solution.
IMHO, the app.config mechanism is not any better than straight XML serialization. It is actually more difficult to access this configuration from a number of different projects. If you are only saving transient state (user options etc) from a WinForms application, then application settings can be convenient for simple data types.
It seems to me like you have another issue that is causing the corruption. I rarely get file corruption with these XML files. Whenever I do, it is related to an exception that is thrown during serialization, not due to application crash etc. If you want to double check this, you might want to serialize to memory stream and then dump the memory stream to disk. You can actually serialize, deserialize the stream to make sure it's valid prior to dumping the file to disk.
Unless you are writing this file a lot I would be skeptical that the file corruption is due to power outages.
Unless you can track down the source of the error, you're only just guessing that it has anything to do with Xml files. It's entirely possible the built-in XmlSerializer is failing .. e.g. you may have a circular reference somewhere, but it's hard to comment unless you know what your error is.
Sometimes using the built-in Xml Serializer isn't the best choice, and when objects get complex, it can be better to perform the serialization and deserialization yourself. You'll have more control and be able to more accurately determine / recover from bad file data.
XDocument doc = new XDocument(
new XElement("attachments",
new XElement("directory", attachmentDirectory),
new XElement("attachment-list",
from attached in attachedFiles
select new XElement("file",
new XAttribute("name", attached.FileName),
new XAttribute("size", attached.FileSize))
)
)
);
Other than that, configuration files are for configuration, not program data. The difference is configuration data shouldn't change often, and normally isn't too directly editable from users. In a winforms app, you don't share data between users in a configuration file. If you do, then you should consider if your app is really a database application.
Since we have made a decision to abdicate from Microsoft Configuration System in 2007 we have not regretted for a second.
Take a look at this: http://blog.aumcode.com/2013/08/aum-configuration-as-facilitated-by-nfx.html
精彩评论