C# serialized object versions - c#

I have the following situation. In my C# application, I have a class which i serialize using XmlSerializer. The class is pretty complex, and an object of my class gets saved on local disc as an application file, which can be opened later (classic save work and reopen work). My problems is that during the development, the class of the object which gets serialized might change. I would like to have a version system, which allows my app to realize that the saved xml it belongs to an older version but still can be opened. Old app versions can not open new xml versions as well.
For example:
class ComplexObject
{
public string settings1;
public string settings2;
}
I serialize object, send app in production.
Tomorrow my class became
class ComplexObject
{
public string settings1;
public string settings2;
public string settings3;
}
How will my new version of app open serialized objects of old class definitions as well as new class definition with no error on loading file to object (deserialization)
Any suggestions and basic samples are welcomed!
Thanks

It all depends on the choice of serializer. In the case of XmlSerializer this is fine and will just work; clients with the new value will load the new value; clients without will not. Sample:
var reader = XmlReader.Create(new StringReader(
#"<ComplexObject><foo>123</foo><bar>abc</bar></ComplexObject>"));
var ser = new XmlSerializer(typeof (ComplexObject));
var obj = (ComplexObject)ser.Deserialize(reader);
with:
public class ComplexObject
{
public string foo;
}
which works and loads foo but not bar.
Do not use BinaryFormatter for this - that leads to a world of hurt. If you want binary output, consider something like protobuf-net which is designed to be overtly accommodating with versioning.

Version-tolerant serialization
In short, you either mark fields as Optional (and fill them with default values) or implement deserialization constructor which will parse values as you want them.

I hope I understood your problem correctly. You're having a class serialized to a file. Then you change the class in memory (e.g you add another property). No you want to deserialize this class from the file. This is no problem as long as you only add new properties. They will be ignored by the deserializer. He creates a new instance of your class (that is the reason, why serializable classes have to have a default constructor) and tries to fill the properties he finds in the stream to derserialize. If you change property's type or remove a property, you won't be able to deserialize that.
One workaround for "remove properties" maybe to keep properties you intentionally wanted to remove and ignore those furthermore.
You can take a look at Version Tolerant Serialization explained in msdn
http://msdn.microsoft.com/en-us/library/ms229752%28v=vs.80%29.aspx

Track 1
You could create some if..else mechanism for a new version file opener which would try to open file from lowest possible version to higher.
Track 2
You could store version information in your files.
class ComplexObject
{
public string settings1;
public string settings2;
public string fileVersion;
}
Track 3
You could use different file extensions for different file versions.(like .doc, .docx)

Related

Load/Deserialize faster Json data to C# object

In my code I use Newtonsoft.Json :
MyCSharpTargetClass foo = JsonConvert.DeserializeObject<MyCSharpTargetClass>(json_string);
The content of the json_string is constant (loaded from a file that never changes).
The functionality is fine but the deserializing process is slow at execution.
My question: is there a way to pre-calculate the object, or to put it in a constant*, or whatever to speed up the execution ?
Note: Actually I didn't manage to put it a constant the result of JsonConvert.DeserializeObject<...>(), but I'm new to C#, so I should have missed something.
Thanks for your help
[EDIT] Solution : Force the Newtonsoft assembly to be loaded at the start of the application.
You do it the same way you would any other object: make it a private member variable, whose value is computed exactly once:
private static readonly MyCSharpTargetClass foo = JsonConvert.DeserializeObject<MyCSharpTargetClass>(json_string);
Or do it in the constructor:
private readonly MyCSharpTargetClass foo;
public MyObject()
{
foo = JsonConvert.DeserializeObject<MyCSharpTargetClass>(json_string);
}
That way the work to deserialize the string is done exactly once.
There's actualy not a lot of thinks you can do to speed this up.
Using ignore attribute, so this fields will not be added. Use this for some properties or calcualatable properties/fields, which can be recalculated later.
Hope this link helps :
https://msdn.microsoft.com/en-us/library/system.runtime.serialization.ignoredatamemberattribute.aspx
Using threads to read/write your objects, if you can customize your data into many files and serialize/deserialize in threads.
Deserialization JSON algorithms requires to read whole file about 3 times.
For better perfomance you can use YAML. Simple as XML/JSON, but with much better perfomance, since it reads file only 1 time.
Using shorter DataMember names to fields
[DataMember(Name = "id")]
public int MyObjectForSomethink{get;set;}

Looking for a viable solution to using XML file as constant data source

I am looking for suggestions on how to best attack my problem.
I have a web application that will utilize a database and XML file as its data source.
Updating the DB is no issue, dealing with the XML file is.
First understand the web app is a bypass to a current(and bad performing production system). So there is no flexibility there.
So in case of the XML file the following steps will need to be performed if a user adds/update/delete a field.
Pull XML file from linux server
Parse XML file into POCOs for the UI
Recreate the XML file from the POCOs with the modifications
Push XML file to the linux server
The only good thing in my favor is that I won't have very many users using this app at a given time.
I would highly recommend looking at the DataContractSerializer for your serialization needs. Your objects would have to follow the same format as the XML, but there is no reason that you can't make those objects your model. Here is an example of marking up a POCO to serialize automatically to and from XML:
[DataContract]
public class Account
{
[DataMember, XmlAttribute]
public string Name { get; set; }
[DataMember]
public double Balance { get; set; }
}
And then you use the serialization code like this:
string serializedAccount = null;
XmlSerializer serializer = new XmlSerializer(typeof(Account));
using(StringWriter writer = new StringWriter())
{
serializer.Serialize(writer, myAccountObject);
serializedAccount = writer.ToString();
}
// serializedAccount should look something like this:
//
// <Account Name="MyName">
// <Balance>100</Balance>
// </Account>
//
// Each of the DataMember and DataContract attributes allow you to override
// names so that you can make them lower case, or provide a more meaningful
// name in your POCO.
Account deserializedAccount = null;
using(StringReader reader = new StringReader(serializedAccount))
{
deserializedAccount = serializer.DeSerialize(reader) as Account;
}
A couple things to keep in mind:
DataContract is an opt in policy. Members are ignored unless you explicitly mark them as ignored.
If you want to explicitly mark a field or property as ignored, use the [IgnoreDataMember] attribute. It can be handy even just for documentation purposes.
Nothing in the serializer prevents you from implementing INotifyPropertyChanged so all your properties can be bindable (handy for WPF)
If your XML format is not what you want to use as a model for your UI, you still may need to map properties in one object to properties in another object. This is still orders of magnitude easier than hand writing the XML reading/writing code yourself.
NOTE: if your server implements a proper SOAP web API, then WCF can take the WSDL and generate the bindings to the API and the objects that need to be serialized. There's a bit more work involved if it's a REST API, but that's also supported.

An easy way to validate an XML against a C# Class

I use the XML format to keep settings for my C# project.
Theses XMLs are deserialized into C# classes.
Often enough, a class design changes but I forget to update the XML. Deserialization usually works fine and missing elements just get their default values.
This behavior is not desirable for me. I would like to have automatic validation that asserts the class and the XML have exactly the same structure.
I know I can create XML schemas (e.g using XSD) for my classes, but I could not figure an easy way to do it automatically and not manually (recall my classes' design changes often). Also, this solution seems kind of unnatural. I do not really need XML schemas. I have classes and their serialized XML instances. Adding schemas seems superfluous.
Thanks a bunch.
Why you don't create a method in your settings class that can be invoked after xml deserialization?
Suppose you have a class like this:
class Settings {
public string Property1 { get; set; }
public int Property2 { get; set; }
public bool IsValid() {
if(string.IsNullOrEmpty(Property1)) return false;
if(Property2 == 0) return false;
}
}
Using IsValid you can check everything in your class. Please, remember that this is an example. I think is good to manage object validation. If you change something in the time, you can edit the validation method to check new situations.
To go with Roberto's idea and take it a step further you could get all the properties via reflection:
var props = yourClass.GetType().GetProperties()
Inside of your validation function you could loop over those properties with:
foreach(var prop in props) // or foreach(var prop in yourClass.GetType().GetProperties())
{
//...Validation of property
}
If one of the properties has its standard-value you throw a custom exception that tells you you did not update your XML-file properly.
You can implement this using Version Tolerant Serialization (VTS) https://msdn.microsoft.com/en-us/library/ms229752%28v=vs.110%29.aspx
The Serialization Callbacks is what you are looking for in the VTS capabilities

Serialization - Viewing the Object Graph from a Stream

I'm wondering if there's a way in which I can create a tree/view of a serialised object graph, and whether anyone has any pointers? EDIT The aim being that should we encounter a de-serialization problem for some reason, that we can actually view/produce a report on the serialized data to help us identify the cause of the problem before having to debug the code. Additionally I want to extend this in the future to take two streams (version 1, version 2) and highlight differences between the two of them to help ensure that we don't accidently remove interesting information during code changes. /EDIT
Traditionally we've used Soap or XML serialization, but these are becoming too restricted for our needs, and Binary serialization would generally do all that we need. The reason that this hasn't been adopted, is because it's much harder to view the serialized contents to help fix upgrade issues etc.
So I've started looking into trying to create a view on the serialized information. I can do this from an ISerializable constructor to a certain extent :
public A(SerializationInfo info, StreamingContext context)
{}
Given the serialization info I can reflect the m_data member and see the actual serialized contents. The problem with this approach is
It will only display a branch from the tree, I want to display the entire tree from the root and it's not really possible to do from this position.
It's not a convenient place to interrogate the information, I'd like to pass a stream to a class and do the work there.
I've seen the ObjectManager class but this works on an existing object graph, whereas I need to be able to work from the stream of data. I've looked through the BinaryFormatted which uses an ObjectReader and a __BinaryParser, hooking into the ObjectManager (which I think will then have the entire contents, just maybe in a flat list), but to replicate this or invoke it all via reflection (2 of those 3 classes are internal) seems like quite a lot of work, so I'm wondering if there's a better approach.
You could put a List<Child class> in every parent class (Even if there the same)
and when you create a child you immediately place it in that list or better yet declare it whilst adding it the list
For instance
ListName.Add(new Child(Constructer args));
Using this you would serialize them as one file which contains the hierarchy of the objects and the objects themselves.
If the parent and child classes are the same there is no reason why you cannot have dynamic and multi leveled hierarchy.
In order to achieve what you describe you would have to deserialize whole object graph from stream without knowing a type from which it was serialized. But this is not possible, because serializer doesn't store such information.
AFAIK it works in a following way. Suppose you have a couple of types:
class A { bool p1 }
class B { string p1; string p2; A p3}
// instantiate them:
var b = new B { p1 = "ppp1", p2 = "ppp2", p3 = new A { p1 = true} };
When serializer is writing this object, it starts walking object graph in some particular order (I assume in alphabetic order) and write object type and then it's contents. So your binary stream will like this:
[B:[string:ppp1][string:ppp2][A:[bool:true]]]
You see, here there are only values and their types. But order is implicit - like it is written.
So, if you change your object B, to suppose
class B { A p1; string p3; string p3;}
Serialzer will fail, because it will try to assing instance of string (which was serialized first) to pointer to A. You may try to reverse engineer how binary serialization works, then you may be able to create a dynamic tree of serialized objects. But this will require considerable effort.
For this purpose I would create class similar to this:
class Node
{
public string NodeType;
public List<Node> Children;
public object NodeValue;
}
Then while you will be reading from stream, you can create those nodes, and recreate whole serialized tree and analyze it.

Where to store configuration information

I have a console application that I am rebuilding from C to C#. This application has to be able to support the legacy method of storing information like parameters from a command-line and parameters from a file (called the system parameters) that customize each run. The system parameters file is in plain-text with a simple key-value structure.
My questions are:
Should I combine these different parameters into a single Configuration object?
How would I call this configuration object from the code to store parameters?
How would I call this configuration object from the code to retrieve parameters?
Should this object be strongly-typed?
I will need access to this structure from a lot of different places in the code. What is the most elegant way to retrieve the values in the object without passing the object itself around everywhere?
I have a feeling that it should be a single, strongly-typed object and that it should be an instantiated object that is retrieved from a repository with a static retrieval method however I really want validation of this method.
I would use a single configuration object like the following:
using System;
using System.IO;
using System.Reflection;
public sealed class Setting {
public static int FrameMax { get; set; }
public static string VideoDir { get; set; }
static readonly string SETTINGS = "Settings.ini";
static readonly Setting instance = new Setting();
Setting() {}
static Setting() {
string property = "";
string[] settings = File.ReadAllLines(SETTINGS);
foreach (string s in settings)
try {
string[] split = s.Split(new char[] { ':' }, 2);
if (split.Length != 2)
continue;
property = split[0].Trim();
string value = split[1].Trim();
PropertyInfo propInfo = instance.GetType().GetProperty(property);
switch (propInfo.PropertyType.Name) {
case "Int32":
propInfo.SetValue(null, Convert.ToInt32(value), null);
break;
case "String":
propInfo.SetValue(null, value, null);
break;
}
} catch {
throw new Exception("Invalid setting '" + property + "'");
}
}
}
Since this is a singleton, it will create one and only one instance of itself the first time a public static property is referenced from the Setting object.
When the object is created, it reads from the Settings.ini file. The settings file is a plain-text file with a simple key : value structure that might look like this:
FrameMax : 12
VideoDir : C:\Videos\Best
The object uses reflection to discover each property and to store its initial value. In this example, two properties have been defined:
public static int FrameMax { get; set; }
public static string VideoDir { get; set; }
The code as written handles Int32 and String types. By adding additional case statements to the switch statement, you could easily add support for types like Float and Decimal.
To change a setting, you would use something like:
Setting.FrameMax = 5;
To retrieve a setting, you would use something like:
if (Setting.FrameMax > 10) ...
You'll notice that all the properties are strongly-typed. Also, you don't have to pass the Setting object around, as all the Setting properties are static and always available everywhere.
I hope this idea is helpful.
I like using Settings. These can be generated automatically either by creating a settings file using the Add New File dialog box, or by adding a default settings file from project properties.
Each setting may be in user or application scope, which controls whether or not the user can change them or they are restricted to their default values. They are easily saved with the Save() method and loaded automatically into the static Default property.
This class seems to be for application or user-based settings. I'm looking for per-run settings. Would you still recommend using this class in that case? – x97mdr
Yes. If you have both user/application based settings and per-run settings you should use two different classes - the normal (saved) settings and the per-run settings.
As long as you don't save the per-run settings, you should be safe and settings are still quite easy to use. These are static settings though. If the same application run needs several instances - this is the wrong approach.
I find that whenever I have to deal with a legacy system, sticking with the old format almost always works best. Often times there are other people using the legacy formats for other tasks (like automation of the app, for example), so if you recode the way the application handles inputs, you might break other systems.
On the other hand, if you are pretty confident that you know all the people using the system, and they tell you that they don't care if you change these types of things, I would probably move everything to XML. Besides all the nice features of XML from an application point of view (like being in ASCII so it's easily modified by humans, being self-documenting, etc ...), XML is also time-saving, in that you don't have to write your own I/O or parser. There's already a wide variety of libraries out there, particularly in .NET 3.0/3.5, that do very well. (As you're moving to C#, I'm guessing you're already thinking along these lines :)
So ultimately, you'd have to base your decision on cost-to-implement: if you lower your cost of implementation by moving to XML or similar, make sure that you don't raise other people's cost of implementation to move to your new application framework.
Good luck!
XmlDocument - you can generate a class definition using XSD.exe

Categories

Resources