A quick way to Object Serialization
Serialization in .Net is one of the more useful features in .Net that I use all the time. Serialization – especially XML Serialization – makes it essentially trivial to write out the content of an object to a file, stream very easily. This is useful to pass data between applications, but also a great simple mechanism for saving and reloading state of applications. In fact, I use Serialization for just about every application to store a number of configuration settings easily.
Although Serialization is pretty straight forward, today I got tired of having to write the same serialization code over and over again. It's not much code, but remembering the stream and formatting options always required me looking this stuff up and fumbling for a few minutes in the docs or for an old sample.
Today, after having done this for the nth time, I added a couple of generic serialization methods to my utility class libraries. The result are the following two static methods:
using System;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
…
/// <summary>
/// Serializes an object instance to a file.
/// </summary>
/// <param name="Instance">the object instance to serialize</param>
/// <param name="Filename"></param>
/// <param name="BinarySerialization">determines whether XML serialization or binary serialization is used</param>
/// <returns></returns>
public static bool SerializeObject(object Instance, string Filename,
bool BinarySerialization)
{
bool retVal = true;
if (!BinarySerialization)
{
XmlTextWriter writer = null;
try
{
XmlSerializer serializer =
new XmlSerializer(Instance.GetType());
// Create an XmlTextWriter using a FileStream.
Stream fs = new FileStream(Filename, FileMode.Create);
writer = new XmlTextWriter(fs, new UTF8Encoding());
writer.Formatting = Formatting.Indented;
writer.IndentChar = ' ';
writer.Indentation = 3;
// Serialize using the XmlTextWriter.
serializer.Serialize(writer,Instance);
}
catch(Exception)
{
retVal = false;
}
finally
{
if (writer != null)
writer.Close();
}
}
else
{
Stream fs = null;
try
{
BinaryFormatter serializer = new BinaryFormatter();
fs = new FileStream(Filename, FileMode.Create);
serializer.Serialize(fs,Instance);
}
catch
{
retVal = false;
}
finally
{
if (fs != null)
fs.Close();
}
}
return retVal;
}
/// <summary>
/// Deserializes an object from file and returns a reference.
/// </summary>
/// <param name="Filename">name of the file to serialize to</param>
/// <param name="ObjectType">The Type of the object. Use typeof(yourobject class)</param>
/// <param name="BinarySerialization">determines whether we use Xml or Binary serialization</param>
/// <returns>Instance of the deserialized object or null. Must be cast to your object type</returns>
public static object DeSerializeObject(string Filename,Type ObjectType,
bool BinarySerialization)
{
object Instance = null;
if (!BinarySerialization)
{
XmlReader reader = null;
XmlSerializer serializer = null;
FileStream fs = null;
try
{
// Create an instance of the XmlSerializer specifying type and namespace.
serializer = new XmlSerializer(ObjectType);
// A FileStream is needed to read the XML document.
fs = new FileStream(Filename, FileMode.Open);
reader = new XmlTextReader(fs);
Instance = serializer.Deserialize(reader);
}
catch
{
return null;
}
finally
{
if (fs != null)
fs.Close();
if (reader != null)
reader.Close();
}
}
else
{
BinaryFormatter serializer = null;
FileStream fs = null;
try
{
serializer = new BinaryFormatter();
fs = new FileStream(Filename, FileMode.Open);
Instance = serializer.Deserialize(fs);
}
catch
{
return null;
}
finally
{
if (fs != null)
fs.Close();
}
}
return Instance;
}
These methods work with file output for serialization since that is the most common scenario I run into as manual serialization usually ends up being a persistence mechanism. It's trivial to work with strings if you need to (see below)...
Both of these methods are static so they require that you pass in the type that you’re dealing with. My primary purpose originally was to serialize and deserialize my business objects, but it is impossible to deserialize an object into the this reference – you always must have variable to deserialize into.
The following example actually serialize an object you might use something like this:
wwUtils.SerializeObject(Configuration,"d:\\temp\\xConf.xml",false);
Then to reload the object:
Configuration = (ConfigClass) DeSerializeObject("d:\\temp\\xConf.xml",
typeof(ConfigClass),false);
Much easier to deal with if you do this on a regular basis. If you need to return a deserialized object in string format you can cheat a little and dump the output to file and read it back in. This is not the most efficient way to do this (a MemoryStream would work better), but it requires very little work:
public string ToXml()
{
wwUtils.SerializeObject(this,TFile,false);
System.IO.StreamReader sr = new System.IO.StreamReader(TFile);
string XML = sr.ReadToEnd();
sr.Close();
File.Delete(TFile);
return XML;
}
Remember that any objects that you want to serialize must be marked with the [Serialiazable()] attribute or inherit from MarshalByRefObject. The object also may not contain any subobjects that may not serialize. For example, a DataRow cannot be serialized. IComponent.ISite cannot be serialized – if you have objects that include non-serializable subobjects serialization will fail. The workaround for this is to make those specific members of the class as non-serializable.
[XmlIgnore] // DataRows can't serialize
public DataRow DataRow
{
get { return this.oDataRow; }
set { this.oDataRow = value; }
}
[NonSerialized]
DataRow oDataRow = null ;
You can use XMLIgnore on properties persisted into XML serialization. Note that this has no effect on binary serialization. For binary serialization use the [NonSerialized] attribute on field values, which causes field values not be persisted and passed forward.
Among other things serialization is a great way to persist data between application runs. I also find it invaluable to use for debugging as I can simply dump state of an object to disk at runtime and review later which can come in handy at times.
Other Posts you might also like
- Adding minimal OWIN Identity Authentication to an Existing ASP.NET MVC Application
- Resolving Paths To Server Relative Paths in .NET Code
- Map Physical Paths with an HttpContext.MapPath() Extension Method in ASP.NET
- Back to Basics: Rewriting a URL in ASP.NET Core
- Getting the Client IP Address in ASP.NET Core
The Voices of Reason
# re: A quick way to Object Serialization
# re: A quick way to Object Serialization
Do you know how to make this Site member non-serializable?
Thank you
# re: A quick way to Object Serialization
Just looking for a work around - Thanks in advance
# re: A quick way to Object Serialization
It appears that sp1 is backwards compatible, and can deserialize earlier objects, but not the other way around.
# re: A quick way to Object Serialization
How to pass this object to another web app as object.I have written deserialisation method in another app where this object is expected.
Your help will be appricated.
Thank you.
Bharat Gadhia
# re: A quick way to Object Serialization
# re: A quick way to Object Serialization
I have a problem with serialization. I'm serializing an ArrayList with my own classes in it. When deserializing this in the same application everything works just fine. But when trying to deserialize it in another application it throws an invalidcastexception. I've tried everything. The classes in both applications are the same and still. It seems like since the assemblyinformation that's saved doesn't fit eachother, that it won't work.
What is wrong and how can I fix it?
# re: A quick way to Object Serialization
We are getting an ObjectType of <<filename>>_aspx+<<objectname>>
HELP!!!
# re: A quick way to Object Serialization
I had the same problem with you.
"Object System.Collections.Comparer has 1 members, number of members deserialized is 0."
Please install .NET 1.1 SP1 on the machine of that developer. That will solve the issue.
( http://www.llblgen.com/tinyforum/Messages.aspx?ThreadID=3155 )
# re: A quick way to Object Serialization
public static Content SerializeCopy(Content content)
{
MemoryStream memoryStream = new MemoryStream();
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(memoryStream, content);
memoryStream.Seek(0, SeekOrigin.Begin);
return (Content)formatter.Deserialize(memoryStream);
}
# re: A quick way to Object Serialization
# re: A quick way to Object Serialization
Does anyone have a solution to this problem at all?
# re: A quick way to Object Serialization
# re: A quick way to Object Serialization
"Unable to find assembly .... "
How can assembly not able to find itself???
I have something like the following.
[Serializable]
[ComVisible(true)]
class myClass
{
....
}
[ComVisible(true)]
class Wrapper
{
public void Wrap()
{
.... // this serializes ArrayList of instances of myClass
}
}
[ComVisible(true)]
class Unwrapper
{
public void Unwrap()
{
.... // this deserializes ArrayList of instances of myClass
}
}
------------------------------
so deserialization works fine when I call my dll from any .NET code, but when I call this dll as a COM dll from other application serialization works fine but during deserialization it tries to find itself and can't :(.
Same dll is used to serialize and deserialize myClass objects...
has anybody solved the problem.
# re: A quick way to Object Serialization
Many thanks!
# re: A quick way to Object Serialization
I am getting the following error while trying to run a report. I am using SQL Server 2005.
w3wp!dataextension!5!6/12/2008-16:56:16:: w WARN: An exception has occurred trying to deserialize the field name. Details: System.ArgumentException: Invalid argument.
at Microsoft.AnalysisServices.AdomdClient.AdomdDataReader.GetOrdinal(String name)
at Microsoft.ReportingServices.DataExtensions.AdoMdDataReader.GetOrdinal(String fieldName)
w3wp!dataextension!5!6/12/2008-16:56:16:: w WARN: The field name '=Space(3*Fields!ParameterLevel.Value) + Fields!ParameterCaption.Value' is invalid.
w3wp!processing!5!6/12/2008-16:56:16:: e ERROR: Throwing Microsoft.ReportingServices.ReportProcessing.ReportProcessingException: There is no data for the field at position 3., ;
Info: Microsoft.ReportingServices.ReportProcessing.ReportProcessingException: There is no data for the field at position 3.
I am not able to get a resolution for this or what it refers to ......stuck up in there ...
Thoughts ?
Thanks for the help :)
# re: A quick way to Object Serialization
resolves the problem defined "assembly not found" when deserializing.
# re: A quick way to Object Serialization
# re: A quick way to Object Serialization
One comment...
On the web, serialization rarely uses an xml file stored on the server to serialize/deserialize objects. It is almost entirely done in memory.
It would be nice to have a simple example that serializes an object in memory from one aspx page and deserializes the object in another aspx page. (Basically serializing the object and deserializing after a postback).
In my mind, serializing using a file is the same as writing to a filestream. Serialization is not necessary. (but I'm new to this so I hope I am wrong).
# re: A quick way to Object Serialization
Im facing a problem in Serialization.
The problem is i have serailized an object in one machine and when i try to deserialize in other machine it throws the following exception.
"Exception Occurred: file name = C:\Program Files\Motorola\CTPU\CDMA\View Templates\Access Decode.mvt Wrong number of Members. Object System.Collections.Comparer has 1 members, number of members deserialized is 0."
When i install the program in some machine it works fine, but in some meachines it does not work fine.
Please help in finding a solution to this.
My Mail Id is obuli666@yahoo.com
Thanks & Regards,
obuliraj.