Reacting on serialize and deserialize of an instance - c#

I have a class which i am serializing. I annotated it with [Serializable] and i am using binary serializer. Everything works fine.
But later i introduced new properties, which cannot be serialized (lets say they contain a lot of mess about GUI which does not need to be rembered). I can compute these properties based on other properties of class.
I need to do it two times, when I serialize - clean mess and enter stabile state ready for serialization. And deserialization - again compute all needed properties.
I need to react on 'events' instance is being serialized/deserialized.
However I can't find these events because I am not implementing the interface ISerializable or abstract class Aserializable but only class atribute [Serializable].
I do not know when class is being serialized because it is not the concern of this class; it is serialized as a field of another class.
Is there a way I can react on those events?

You can use OnDeserializedAttribute and its related attributes (OnSerializing, OnSerialized, OnDeserializing) to create special methods that are called during the serialization/deserialization process.

Build Custome Serialization by Implementing ISerializable. Use OnSerializingAttribute, to manipulate object before serilazation and OnDeserializingAttribute, to manipulate before deserialization.

Have you considered per chance the [XmlIgnoreAttribute] attribute? It will prevent a property to be serialized. No need to tamper withe the serialization workflow.
My bad, didn't realize you wanted to reload some property on deserialization. So why not serialize these? In an optional subObject, or whatever?

Related

Adding a method to an object that is serialized, but it doesnt' need to be serialized

I have an object that is currently serialized, and I want to do add a method to this class. The method shouldn't be serialized as it doesn't hold any state or anything, but it will modify the classes data but this doesn't need to be serialized (it will parse the value of a serializable string property).
How can I add this method? Or should I have this method on another utility class instead?
Methods aren't serialized. Only properties and fields are serialized. And Properties are only eligible for serialization if using DataContractSerializer (BinaryFormatter will only serialize Properties' underlying fields).
Adding this method won't be a problem, methods aren't serialized.
If you have access to the class then as I understand it serialization deals with properties and fields. Methods don't need to be and don't get serialized. They process the data
Quick answer: Most cases shouldn't affect unserialize an object.
Only fields are serialized. Methods and properties arent (properties are methods). The XmlSerializer is an exception; it only looks at public properties, and those must be public get / set if you are to deserialize them.

Object xml deserialization issue?

My objects has a parent-child relationship. Each child object has a Parent property pointing to its container. When this object is created in the app, it's set, and thus no problem. This Parent property is marked with XmlIgnore attribute, because it needs to be set to its run-time parent instance. So, what's the best way to initialize this Parent property after the object is deserialized? Is there a 'Deserialize completed' event or something similar?
EDIT: I'm talking about XmlSerializer in C# WPF. I don't want binary serializer.
Your question is somewhat lacking in details, but from some of the attributes and properties that you describe, I'm going to assume that you're using the XMLSerializer in the .NET Framework.
You may know about the OnDeserialized attribute, which you can use to mark a particular method that you want to be called after an object has been deserialized. Unfortunately, this only works with the Binary, SOAP, and DataAttribute formatters, not for XMLSerializer.
In order to achieve this same functionality using the XMLSerializer, you will have to implement the IXmlSerializable interface yourself on the class that you want to serialize to XML. This will allow you to complete control over how instances of your class are serialized and deserialized, including code that is run to initialize the Parent property after an object is deserialized.
There is a good example article on CodeProject that describes how to correctly implement IXmlSerializable available here.
XmlSerializer does not provide serialization callbacks, I'm afraid. One way to do this is for the parent to handle this when adding - but you will need a custom collection (perhaps inherited from Collection<T>) that during Add/Remove calls some method on the child to add (or remove, if removing from the collection) the parent.
Alternatively - consider simply making it a one-way only tree - i.e. the child doesn't have a parent property.
Another option is simply to walk the model through code after deserialization, and fixup any parent values.
The final option is to implement IXmlSerializable, but that is very hard get right.

Why do you have to mark a class with the attribute [serializable]?

Seeing as you can convert any document to a byte array and save it to disk, and then rebuild the file to its original form (as long as you have meta data for its filename etc.).
Why do you have to mark a class with [Serializable] etc? Is that just the same idea, "meta data" type information so when you cast the object to its class things are mapped properly?
Binary serialization is pretty powerful, it can create an instance of a class without running the constructor and can set fields in your class that you declared private. Regular code can of course not do this. By applying the [Serializable] attribute, you explicitly give it the go-ahead to mess with your private parts. And you implicitly give that permission to only the BinaryFormatter class.
XML serialization doesn't need this kind of okay, it only serializes members that are public.
DataContractSerializer can serialize private members as well. It therefore needs an explicit okay again, now with the [DataContract] attribute.
First off, you don't have to.
It is simply a marker interface that tells the serializer that the class is composed of items that it can serialize (which may or may not be true) and that is can use the default serialization.
The XMLSerializer has the additional requirement to have a zero parameter constructor to the class.
There are other serializers that use contracts for serialization (such as the DataContractSerializer) - they give you more control over serialization than simply marking a class as Serializable. You can also get more control by implementing the ISerializable interface.
It's basically metadata that indicates that a class can be serialized, nothing more.
It is required by a lot of framework serializers, which refuse to deal with types not having this attribute applied to them.
Serialization can create security holes and may be plagued by versioning problems. On top of that, for some classes, the very idea of serialization is outright nonsense.
For details, see the excellent answers to Why Java needs Serializable interface?, especially this one, this one, and this one. They make the case that serialization should be a feature you have to explicitly opt into.
For a counterpoint, the accepted answer to that question makes the case that classes should be serializable by default.
It indicates to the serializer that you want that class to be serialized as you may not want all properties or classes to be serialized.
I see it as a reminder that I will allow the class to be serialized. So you don't implicitly serialize something you shouldn't.
Don't know it that is designers' intention.
BTW, I just love BinaryFormatter and use it as much as I can. It handles pretty much of the stuff automatically (like rebuilding complex object graphs with recurring references spread throughout the graph).

Serializing an object but none of its references c#

I have a situation where I need to serialize an object but don't want to serialize any of its references. This is because I don't know in advance which dlls the object might be referencing and therefore can't ensure that they are serializable objects. This has arisen from needing to serialise plugins to preserve their state.
Am I right in thinking that this is the case with XML serialization (shallow)? But that this will ignore anything private in the object - which isn't what I want?
Is this somehow possible?
Xml Serialization will only work on things that are publicly accessible. Also, unless you mark a public property / field with the [XmlIgnore] attribute, it will be serialized.
If you're just looking at some method of serialization, then use binary serialization. It will serialize the internal state of the object (all fields, private or otherwise). You can use the [NonSerialized] attribute to ignore specific references if you want.
If you know at the type declaration time which references should not be serialized you can use binary serialization and filter out members with the [NonSerialized] attribute.
Put NonSerialized attribute in case of binary and XmlIgnore attribute in case of xml serialization to reference properties or fields
You do know which properties you can serialize, though, correct? Are these plugins implementing a common interface? If that is the case, you should be able to write a generic serializer that will only serialize the specific properties that you choose.
Here is a basic example that will give you the idea of what you need to do:
Object Serialization using C#
If you are just looking to serialize native types within your class instances, you should just be able to implement ISerializable, though, and decorate the properties that you do not want to be serialized.
You can try something like this:
Type myType = currentObject.GetType();
Then check to see if the object is serializable by using:
myType.IsSerializable; //returns a bool
That should tell you whether or not the object is serializable. If you really need to know whether every single object inside of a class is serializable, such as other nested classes or custom types, then you could probably use reflection to read each object, use the code above, and verify whether or not it is serializable. This, however, might be a more complicated approach, and may not be plausible, especially if you have overhead issues to deal with.
It may be useful for you to separate what you want to persist from how you persist it.
It seems like you want control over how you want to persist data, but obviously, cannot know what it is, because of your plugin model.
One scheme that may make sense to you is to give your plugins some sort of object or interface they can write to and read from when its time to save / load. Its fine to document these constraints.
For example, when persisting, allow your plugins to pass to you:
some arbitrary byte array which they are responsible for serializing / deserializing. Then it is a plugins responsibility to make sure they use objects that are appropriately serializable.
a dictionary of strings
an xml file
others...
Store this information per plugin (in whichever form you want), and loading up again, pass back the same information.
This is simply an approach around the fact that in the end, the plugin knows what it needs to save, and needs to own that piece of information.

Having DataContractSerializer serialize the same class in two different ways?

I'm using the DataContractSerializer to serialize an objects properties and fields marked with DataMember attributes to xml.
Now a have another use case for the same class, where I need to serialize other properties and other fields.
Are there a way to add "another DataMemberAttribute" that can be used for my other serialization scenario?
No, basically.
If you want to use the existing DataContractSerializer, you'll have to maintain a second version of the DTO class and convert the data between them.
Options if you are writing your own serialization code:
declare your own [DataMember]-style attribute(s) and interpret them at runtime in your own serialization code
use a "buddy class"
use external metadata (such as a file)
use code-based configuration (i.e. via a DSL)
In reality, I expect the first will be the simplest choice.
In a similar scenario in the past, we've taken an Object Oriented approach, and created a new class that extends from the main class.
To help you achieve inhertience with the DataContractSerializer, check out KnownTypeAttribute
In one of your comments to your question,
If the same class is implementing multiple interfaces, certain data elements may be relevant to only one of the interfaces.
If that is the case in your scenario, then perhaps your Data Service Contracts should be exposing just the Interfaces, and not the Class?
For example, if you have a class like:
[DataContract]
public class DataObject : IRed, IBlue
then rather than have your operation contract expose DataObject, you have two operation contracts one for IRed and one for IBlue.
This eliminates the need for custom serialization code.
There is a way to do it, but it's an ugly hack.
The DataContractSerializer can serialize objects that implement the IXmlSerializable interface. You could implement the interface and create your own ReadXml(XmlReader reader) and WriteXml(XmlWriter writer) methods that could serialize the object in different ways.
Note that you'd have to have a flag embedded within the class itself to determine which way to serialize the object. (There's no way to tell the DataContractSerializer which mode to use, so the flag has to be contained in the object itself.)
A second version of the DTO class, as #Marc suggests, would be much cleaner.

Categories