How to Serialize a non Sertilizable object into Binary?

Hi,
I have an object ObjXML of type XmlDocument (object may be of any non serializable class). I have to Serialize it into Binary. I know that XmlDocument does not implement ISerializeable.That's why according to framework we cannot serialize it.
So is there anyway around to get this object (ObjXML) into Binary.
I will behighlyobliged to your help.
Regards
Muhammad Waqas Bashir
[1564 byte] By [MuhammadWaqasBashir] at [2008-3-1]
# 1

You can implement ISerializationSurrogate to either serialize non-serializable objects, or override serialization for classes you either can't extend or don't want to. You then add this surrogate to an ISurrogateSelector - for which SurrogateSelector in the BCL is a default implementation - and pass this to your formatter. An example is given below. Compile this, run it, and - if you'd like - open Example.bin to see your document serialized using a BinaryFormatter.

using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Xml;

class SerializeXmlDocument
{
static void Main()
{
// Create an XmlDocument to serialize.
XmlDocument doc = new XmlDocument();
doc.LoadXml(@"
<root>
<branch>
<leaf>First leaf</leaf>
<leaf>Second leaf</leaf>
</branch>
<branch>
<leaf>Third leaf</leaf>
</branch>
</root>");

// Pack it into our example serializable object.
Tree tree = new Tree("Example", doc);

// Create a serialization surrogate to serialize the XmlDocument.
XmlDocumentSerializer docSerializer = new XmlDocumentSerializer("doc");

// Create the surrogate selector.
SurrogateSelector selector = new SurrogateSelector();
selector.AddSurrogate(typeof(XmlDocument), new StreamingContext(StreamingContextStates.All),
docSerializer);

// Now serialize the object to a binary file.
using (FileStream file = File.Create("Example.bin"))
{
BinaryFormatter formatter = new BinaryFormatter(selector,
new StreamingContext(StreamingContextStates.File));
formatter.Serialize(file, tree);
}
}
}

[Serializable]
class Tree
{
string name;
XmlDocument doc;

internal Tree(string name, XmlDocument doc)
{
this.name = name;
this.doc = doc;
}

public string Name { get { return name; } }
public XmlDocument Document { get { return doc; } }
}

class XmlDocumentSerializer : ISerializationSurrogate
{
string name;
// Prevent default instantiation.
XmlDocumentSerializer() {}

internal XmlDocumentSerializer(string name)
{
if (name == null)
throw new ArgumentNullException("name");

this.name = name;
}
public void GetObjectData(object obj, SerializationInfo info, StreamingContext context)
{
XmlDocument doc = obj as XmlDocument;
if (doc != null)
{
using (StringWriter writer = new StringWriter())
{
doc.Save(writer);

// Save the string to the SerializationInfo.
info.AddValue(name, writer.ToString());
}
}
}

public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
{
string xml = info.GetString(name);
if (xml != null)
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
return doc;
}

return null;
}
}

HeathStewart at 2007-9-9 > top of Msdn Tech,.NET Development,.NET Remoting and Runtime Serialization...
# 2
Thankyou very much for your prompt reply. Your Code is perfect for XMLDocument serialization. But can you please send me generic sample code for the serializaiton of any object who does not implement iserialization.

For example:-

Dim arr1 As Byte() = Nothing

if obj.isSerializable = false then
arr1 = CustomSerializer(obj)
end if
function CustomSerializer(obj) as binary()

// How to implement it....
end function

MuhammadWaqasBashir at 2007-9-9 > top of Msdn Tech,.NET Development,.NET Remoting and Runtime Serialization...
# 3
That wouldn't be possible using serialization surrogates since you have to associate the surrogate with a type. Default serialization does, however, serialize all public and private fields so you could use reflection to get fields of an object.

You really should be careful about serializing non-serializable objects, though. For some objects it's fine, but for other objects - like Windows Forms controls - you typically shouldn't. In the case of controls, they are tied to a Window handle that is valid only for your machine and only for that instance of your application. Attempting to deserialize the control on another machine or for another run of your application could simply fail or have disasterous results.

HeathStewart at 2007-9-9 > top of Msdn Tech,.NET Development,.NET Remoting and Runtime Serialization...
# 4
Thankyou very much you solved my problem.

Regards,
Muhammad

MuhammadWaqasBashir at 2007-9-9 > top of Msdn Tech,.NET Development,.NET Remoting and Runtime Serialization...
# 5
Hi!
I need to serialize XmlDocument to send it using remoting over tcp/binary channel. I created new class that inherts XmlDocuments and implements ISerialization and it seems to work just fine, but as I'm pretty new to this topic I'm not sure if that does something it shouldn't because the code just seems too simple...
Anyway, here's the code:



using System;
using System.Xml;
using System.Runtime.Serialization
public class MyXmlDocument:XmlDocument,ISerializable
{
public MyXmlDocument():base(){}

protected MyXmlDocument(SerializationInfo info, StreamingContext context)
{
this.LoadXml(info.GetString("xmlDocument");
}

public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("xmlDocument", this.OuterXml, typeof(string));
}
}

Please comment this solution if you know a better way to do this job...
Is there any way to send the whole XmlDocument object byte by byte using the same channel?

Thank you very much!

DamienArmstrong at 2007-9-9 > top of Msdn Tech,.NET Development,.NET Remoting and Runtime Serialization...

.NET Development

Site Classified