I am using the following methods to serialize and deserialize .NET objects:
public static string SerializeToBase64(object data)
{
var stream = new MemoryStream();
var formatter = new BinaryFormatter();
formatter.Serialize(stream, data);
stream.Position = 0;
return Convert.ToBase64String(stream.ToArray());
}
public static object DeserializeFromBase64(string data)
{
var stream = new MemoryStream(Convert.FromBase64String(data));
stream.Position = 0;
var formatter = new BinaryFormatter();
return formatter.Deserialize(stream);
}
These methods seem to work fine when working with simple classes marked with the [Serializable] attribute.
But I need to use this code to serialize entity classes (also maked as Serializable) created by an ORM framework, whereby each entity class is derived from a base class for which I do not have source code.
When working with instances of an entity class, it completes serialization without exceptions, but deserialization always throws a null reference exception when excecuting formatter.Deserialize().
I am not very familiar with the process of serialization, but I assume this problem must be caused by something anomalous in the state of the target object. Is there a standard set of criteria that an object must meet before serialization?
Any other debugging suggestions would be appreciated.
Thanks,
Tim
UPDATE:
After further experimentation, I think I have discovered the cause of the problem. The target object has events that are handled by another class that is not marked as serializable, as described in this post.
What's interesting is that serialaztion works correctly, even with the event handlers attached - it's deserialization that fails.
But I have tested by temporarily removing the event handlers and both serialization and deserialization works correctly, so I assume this is the problem. However, since I don't have access to the code in which the events are declared, I can't immediately see how to implement the solution described above. It may be that I have to modify my serialization process to remove and then reinstate the event handlers.
Which ORM framework is it? Note that ORM-generated types tend to be particularly obnoxious when used with BinaryFormatter, since they aren't always "POCO": they often have fields that relate to the ORM - so creating them standalone has issues. In short, I'm not hugely surprised that it doesn't work in this case.
You might want to consider using something like DataContractSerializer, XmlSerializer, protobuf-net, or maybe NetDataContractSerializer - these all do a similar job, but because they work on public properties (rather than fields) they tend to be more effective - and indeed many have inbuilt support for these approaches for use as a DTO.
Can you use Reflector on the ORM base class assembly? There could be some custom deserialization code which is causing the exception (i.e. it implements the ISerializable interface). If you can find out of that is the case, and what it is doing, you might be able to set enough state in the subclass' instance to keep it from happening. On the other hand, if it has a bug, then you're a bit out of luck.
Related
I use protobuf-net serializer like this:
ProtoBuf.Serializer.Serialize(fileStream, data);
How do I get a non-static serializer instance? I want to use it something like this:
var myProtobufNetSerializer = MyProtobufNetSerializerFactory();
myProtobufNetSerializer.Serialize(fileStream, data);
Edit:
Marc Gravell, the protobuf-net's author, replied (to this question) in his answer that it's possible, but I couldn't find how...
The important question I have is why do you want to do that? The static methods actually just expose the v1 API on the default instanc, aka RuntimeTypeModel.Default. So I could answer your question with just:
TypeModel serializer = RuntimeTypeModel.Default;
However, there would be very little benefit to doing this - you might just as well use the static methods. If, however, you want to do something more interesting, then you probably want a custom model:
RuntimeTypeModel serializer = RuntimeTypeModel.Create();
// exercise for reader: configure it, store it somewhere, re-use it
You should not create a new TypeModel per serialization required, since the TypeModel (or more specifically: RuntimeTypeModel) caches the generated strategies internally. It would be inefficient and a memory drain to keep doing this unnecessarily.
Times when you might not want to use the default type-model:
you need to support 2 different incompatible layouts (perhaps for versioning reasons) at the same time
you are using a runtime that doesn't support reflection-emit, and must use pre-built serializer types
you are doing unit testing of the library itself
probably a few others that I'm not remembering
I am trying to serialize objects into xml. I have setup up
public class Foo<t>
{
[XmlElement(ElementName ="test")]
public <t> bar {
get
{
var descriptor = TypeDescriptor.GetProperties(this.GetType())["bar"];
var attrib =(XmlElementAttribute)descriptor.Attributes[typeof(XmlElementAttribute)];
FieldInfo ElementName = attrib.GetType().GetProperty("ElementName")
ElementName.SetValue(attrib, "success");
}
set{}
}
I want to change XmlElement.ElementName at run time but so far have been unsucessfull.
According to this blog you should be able to do it. Also this SO post indicates that I am on the right track.
My Questions are Is what I want to do possible? How do I achieve this?
EDIT:
I want the xml node to be called 'Success' instead of 'test'
The technique in that article only works for .NET components that depend on the TypeDescriptor system, which is a higher level abstraction than raw reflection. XmlSerializer is not one of those components as far as I know.
The closest you can come to "changing attributes at runtime" with respect to XmlSerializer is using XmlAttributeOverrides, but I forget how to use that because I've used it so infrequently. That only allows you to change them for the entire type though, not individual instances as you seem to want. This is partly because XmlSerializer actually compiles a serialization delegate internally that it uses over and over to serialize your type for reasons of performance.
Your best bet is probably to just implement the IXmlSerializable interface to customize the serialization for that particular class. XmlSerializer will honor that interface, and it will allow you to have 100% control over the XML by using XmlReader / XmlWriter. It is more difficult to have to manually write the serialization code, but you have much more control. And you only have to do it for the types in your graph that require custom handling. For an example of using IXmlSerializable see my answer to Override XML Serialization Method.
I am working on a program, where I save it's project files by serializing Project class.
Because I am still working on it, some classes, that are part of Project class, do change from time to time (e.g. class got new property). It makes "simple" deserialization impossible.
Is there any way to solve it ? I mean, without writng custom serializer ? (which probably is something high above my level for now)
Just in case, I am using BinaryFormatter.
I hope I understood your problem correctly. You have a class serialized to a file which you have since changed in the program (e.g you have added another property). Now you want to deserialize this class from the file. This is not a problem as long as you have only added new properties. They will be ignored by the deserializer. It 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 it finds in the stream to derserialize. If you change a property's type or remove a property, you won't be able to deserialize the original file.
One workaround for removing properties is to keep them in the class, but just stop using them in the rest of the program. A workaround for properties that have been changed to a different type could look something like this:
[Serializable]
public class MyClass
{
int? newProperty;
[XmlElement("Property")]
public string OldProperty
{
get { return string.Empty; }
set
{
if (!newProperty.HasValue)
{
int temp;
if (int.TryParse(value, out temp))
{
newProperty.Value = temp;
}
}
}
}
public int NewProperty
{
get { return newPropery.HasValue ? newProperty.Value : 0; }
set { newProperty.Value = value; }
}
}
From my experience, I've found using BinaryFormatter for serialization/de-serialization of data types that are going to change a really bad idea. If something changes in your data type, from what I know the BinaryFormatter will fail in the process.
To overcome this issue in the data types I was using, I had to write my own serializer, which wasn't actually that much of a major task. You can use the BinaryReader and BinaryWriter classes to read and write the data in and out of your type. That way you can control the data you are expecting and handle any missing data either by adding default values, skipping the property altogether, or throwing some form of Exception to signify corrupt data. Refer to the MSDN article links above for more information.
With help from Merlyn Morgan-Graham's comments I've found solution, that will work for me.
Versioning described in Version Tolerant Serialization is really good idea, but when I use only [Serializable] attribute.
I forgot to write (my mistake), that I am using ISerializable interface.
I've found, that in deserialization constructor SerializationInfo object has MemberCount property, which solves my problem if I only add new properties/members from time to time. With this information, new members/properties, that can't be deserialized from older file, can be set to default or maybe I can use some prompt form.
Other way here would be using something like assembly version in deserialization, as a first deserialized member. This can solve deserialization problems with more complex class changes.
Either way, I agree with Merylin - "if you can't script something, you shouldn't be building it". ;)
I am trying to deserialize "SomeClass" with an older version of an application. I get this below exception
System.Runtime.Serialization.SerializationException: The ObjectManager found an invalid number of fixups. This usually indicates a problem in the Formatter.
Deserialization throws exception when I serialize version 0.9 and try to deserialize using version 0.8. I thought the OptionalField attribute would do the trick, but it didn't.
// Version 0.8
[Serializable()]
class Foo{
Bar b;
}
// Version 0.9
[Serializable()]
class Foo{
Bar b;
[OptionalField]
Zoo z;
}
Given that I cannot change version 0.8, how should I add more state to Foo object such that previous versions can deserialize whatever they can?
Any pointer will be really appreciated.
Update 1
Bar and Zoo are other classes which are serializable and contains Hashtables and other serializable stuff. Everything is serializable in those classes.
Also, I don't have any struts.
First, never NEVER use the CLR's serialization functions for anything that resembles long-term storage. We make that mistake usually once, put objects in a blob database field and pat ourselves in the back thinking we're clever. And then the CLR gets a patch or our assemblies change versions and you're screwed. So don't do it.
If you still want to do it, the best way to manage the problem is to create your own SerializationBinder that looks something like this:
public sealed class CustomBinder : SerializationBinder {
public override Type BindToType(string assemblyName, string typeName) {
Type typeToDeserialize = null;
if (typeName.IndexOf("SomeType") != -1) {
typeToDeserialize = typeof(Foo.Bar.Bax.NewType);
}
else if (typeName.IndexOf("SomeOtherType") != -1) {
typeToDeserialize = typeof(Foo.Bar.Bax.SomeOtherNewType);
}
else {
// ... etc
}
return typeToDeserialize;
}
}
Set the Binder property of the formatter you're using prior to deserializing so that it overrides the defaults.
Note that I'm not offering a drop-in solution here, I'm recommending how to solve the problem. Once you've converted out of whatever you're doing, investigate other serialization technologies like protobuf, or write your own. Either way you should never rely on the CLR for long-term serialization support.
If constructors for each version are compatible (e.g. there is a parameterless or Foo(Bar b) constructor for both versions) you can call
BinaryFormatter formatter = new BinaryFormatter();
formatter.AssemblyFormat = Formatters.FormatterAssemblyStyle.Simple;
Before deserializing your stream.
As an advisory to people investigating this issue "before it is too late"... I strongly advise against persisting via BinaryFormatter. It is OK for transient transfer between 2 app-domains that are in sync, but that is about it IMO. Other serialization tools exist that don't have these issues. In terms of binary, protobuf-net is a pretty reasonable option - allowing add/remove/rename etc without pain.
It seems that one way to do this would be to have a versioned object, that way you could try deserializing the object using the latest version. If that didn't work, step back a version until it's successful. Then once you have your object, update it to the latest version of the object and use default values for any fields you don't have data for.
The optional field attribute should have done the trick. Can you post the actual classes that you are trying to serialize.
You could try these things first -
convert structs if any to classes
try Soap Serialization instead of binary serilization
I have an application which supports multiple types and versions of some devices. It can connect to these devices and retrieve various information.
Depending on the type of the device, I have (among other things) a class which can contain various properties. Some properties are common to all devices, some are unique to a particular device.
This data is serialized to xml.
What would be a preferred way to implement a class which would support future properties in future versions of these devices, as well as be backwards compatible with previous application versions?
I can think of several ways, but I find none of them great:
Use a collection of name-value pairs:
pros: good backward compatibility (both xml and previous versions of my app) and extensibility,
cons: no type safety, no intellisense, requires implementation of custom xml serialization (to handle different value objects)
Create derived properties class for each new device:
pros: type safety
cons: have to use XmlInclude or custom serialization to deserialize derived classes, no backward compatibility with previous xml schema (although by implementing custom serialization I could skip unknown properties?), requires casting for accessing properties in derived classes.
Another way to do it?
I am using C#, by the way.
How about something similar to a PropertyBag ?
If you're not limited to interoperability with an external schema, then you should use Runtime Serialization and the SoapFormatter. The pattern for runtime serialization permits derived classes to specify which of their properties need to be serialized and what to do with them when deserialized.
The XML Serializer requires XmlInclude because, in effect, it needs to define the schema to use.
I like name/value sets for this sort of thing.
Many of your cons can be dealt with -- consider a base class that acts as a general name/value set with no-op methods for validating incoming name/value pairs. For known sets of names (i.e. keys), you can create derived classes that implement validation methods.
For example, Printer may have a known key "PrintsColor" that can only be "true" or "false". If someone tries to load PrintsColor = "CMYK", your Printer class would throw an exception.
Depending on what you're doing, you can go a few different ways in terms of making the validation more convenient -- utility methods in the base class (e.g. checkForValidBoolean()) or a base class that accepts name/type information in its constructor for cleaner code in your derived classes, and perhaps a mostly automated XML serialization.
For intellisense -- your derived classes could have basic accessors that are implemented in terms of the key lookup. Intellisense would present those accessor names.
This approach has worked well for me -- there's sort of a short-sightedness to classic OO design, especially for large systems with plugged-in components. IMO, the clunkier type checking here is a big of a drag, but the flexibility make it worthwhile.
I believe that creating derived properties is the best choice.
You can design your new classes using xml schema. And then just generate the class code with xsd.exe.
With .net isn't hard to develop a generic class that can serialize and deserialize all types to and from xml.
public static String toXmlString<T>(T value)
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
StringWriter stringWriter = new StringWriter();
try { xmlSerializer.Serialize(stringWriter, value); }
catch (Exception e)
{
throw(e);
}
finally { stringWriter.Dispose(); }
String xml = stringWriter.ToString();
stringWriter.Dispose();
return xml;
}
public static T fromXmlFile<T>(string fileName, Encoding encoding)
{
Stream stream;
try { stream = File.OpenRead(fileName); }
catch (Exception e)
{
e.Data.Add("File Name", fileName);
e.Data.Add("Type", typeof(T).ToString());
throw(e);
}
BufferedStream bufferedStream = new BufferedStream(stream);
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
TextReader textReader;
if (encoding == null)
textReader = new StreamReader(bufferedStream);
else
textReader = new StreamReader(bufferedStream, encoding);
T value;
try { value = (T)xmlSerializer.Deserialize(textReader); }
catch (Exception e)
{
e.Data.Add("File Name", fileName);
e.Data.Add("Type", typeof(T).ToString());
throw(e);
}
finally
{
textReader.Dispose();
bufferedStream.Dispose();
}
return value;
}
Programatically speaking, this sounds like it might be a job for the Decorator Pattern. Essentially, you have a super class which defines a common interface for all these types of devices. Then you have decorator classes which have other properties which a device might have. And, when creating these devices, you can dynamically add these decorations to define new properties for the device. Graphically:
You can look at the Wikipedia page for a more detailed description. After that, it would just be a matter of doign some serialization to tell the program which decorators to load.
The general idea of what you're trying to accomplish here is precisely what the EAV pattern solves. EAV is a pattern most commonly used in database development but the concept is equally valid for applications.