Pass in an object reference when Deserializing - c#

I have an object that is deserialized with this:
public object DeSerializeObject(string filename)
{
object objectToSerialize;
Stream stream = File.Open(filename, FileMode.Open);
BinaryFormatter bFormatter = new BinaryFormatter();
objectToSerialize = (object)bFormatter.Deserialize(stream);
stream.Close();
return objectToSerialize;
}
public GUI_Settings(SerializationInfo info, StreamingContext ctxt)
{
PrinterFont = (Font)info.GetValue("_printFont", typeof(Font));
}
How could I pass in and object as I deserialize it? Kind of like this
public object DeSerializeObject(string filename, someObject thing)
{
......
objectToSerialize = (object)bFormatter.Deserialize(stream, thing);
.....
}
public GUI_Settings(SerializationInfo info, StreamingContext ctxt, someObject thing)
{
PrinterFont = (Font)info.GetValue("_printFont", typeof(Font));
_thing = thing;
}
I'm not quite sure if I explained it clearly let me try again.
Inside of my main class I say
_settings = (GUI_Settings)new ObjectSerializing()
.DeSerializeObject("Settings.data");
or if I understand what Jalal Aldeen Saa'd said
_settings = (GUI_Settings)ObjectSerializing
.DeserializeFromFile<GUI_Settings>("Settings.data");
When the code runs I need to send it a reference to _backend type backEndInitializer. This reference is held within this main class. GUI_Settings is the type that I am deserializing. _backend is the reference that I need to send the GUI_Settings() method to use.
Answer:
public static object DeSerializeObject(string filename, backEndInitializer backend)
{
object state = backend; // your object
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bFormatter =
new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(
null,
new System.Runtime.Serialization.StreamingContext(
System.Runtime.Serialization.StreamingContextStates.All,
state)); // pass it in
object objectToSerialize;
Stream stream = File.Open(filename, FileMode.Open);
//BinaryFormatter bFormatter = new BinaryFormatter();
objectToSerialize = (object)bFormatter.Deserialize(stream);
stream.Close();
return objectToSerialize;
}
Then in the class that is being deserialized
public GUI_Settings(SerializationInfo info, StreamingContext ctxt)
{
_backend = (backEndInitializer) ctxt.Context;
}

object state = null; // your object
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter =
new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(
null,
new System.Runtime.Serialization.StreamingContext(
System.Runtime.Serialization.StreamingContextStates.All,
state)); // pass it in
From there you can access it object in the context argument in your deserialization constructor. The StreamingContext will have a reference to this instance

Use generics to pass the type of the object that will be deserialized:
public static T DeserializeFromFile<T>(string fileName) where T : class
{
using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
BinaryFormatter formatter = new BinaryFormatter();
return (T)formatter.Deserialize(stream);
}
}
Usage:
Thing deserialized = DeserializeFromFile<Thing>(filePath);

Related

How to inject an object to Serialize to File?

The problem is simple, I want to create a method to serialize and another to open it by passing any object structure. I have the following which is what I believed should work but, guess what, it doesn't:
List<string> list = new List<string>();
list.Add("aaa");
list.Add("bbb");
FileSystem.SerializeToFile(list, "");
List<string> anotherList = FileSystem.OpenSerialized(typeof(List<string>), "");
public class FileSystem
{
public static void SerializeToFile(object toSerialize, string fileName)
{
XmlSerializer writer = new XmlSerializer(typeof(object));
StreamWriter file = new StreamWriter(fileName);
writer.Serialize(file, toSerialize);
file.Close();
}
public static object OpenSerialized(Type type, string fileName)
{
XmlSerializer serializer = new XmlSerializer(typeof(object));
StreamReader reader = new StreamReader(fileName);
object something = serializer.Deserialize(reader);
return something;
}
}
The serializer’s constructor requires a reference to the type of object it should work, slightly modified your code to fit to requirement.
public class FileSystem
{
public static void SerializeToFile<T>(T toSerialize, string fileName)
{
XmlSerializer writer = new XmlSerializer(typeof(T));
StreamWriter file = new StreamWriter(fileName);
writer.Serialize(file, toSerialize);
file.Close();
}
public static T OpenSerialized<T>(string fileName)
{
XmlSerializer serializer = new XmlSerializer(typeof(T));
StreamReader reader = new StreamReader(fileName);
object something = serializer.Deserialize(reader);
return (T)something;
}
}
and now we can use this as
List<string> list = new List<string>();
list.Add("aaa");
list.Add("bbb");
FileSystem.SerializeToFile(list, #"d:\test.txt");
List<string> anotherList = FileSystem.OpenSerialized<List<string>>(#"d:\test.txt");

Is there any design pattern available when using XML serialization in C#

I am using Serialization and De serialization for parsing and creating XML content. Is there any Design pattern available particularly for this serialization in C# , so that the design pattern can be used for efficient handling of serialization ?
Depending on the use case, 'DataContract' may be a good way for you to serialize/deserialize your objects -
https://msdn.microsoft.com/en-us/library/vstudio/system.runtime.serialization.datacontractattribute%28v=vs.100%29.aspx
namespace DataContractAttributeExample
{
// Set the Name and Namespace properties to new values.
[DataContract(Name = "Customer", Namespace = "http://www.contoso.com")]
class Person : IExtensibleDataObject
{
// To implement the IExtensibleDataObject interface, you must also
// implement the ExtensionData property.
private ExtensionDataObject extensionDataObjectValue;
public ExtensionDataObject ExtensionData
{
get
{
return extensionDataObjectValue;
}
set
{
extensionDataObjectValue = value;
}
}
[DataMember(Name = "CustName")]
internal string Name;
[DataMember(Name = "CustID")]
internal int ID;
public Person(string newName, int newID)
{
Name = newName;
ID = newID;
}
}
class Test
{
public static void Main()
{
try
{
WriteObject("DataContractExample.xml");
ReadObject("DataContractExample.xml");
Console.WriteLine("Press Enter to end");
Console.ReadLine();
}
catch (SerializationException se)
{
Console.WriteLine
("The serialization operation failed. Reason: {0}",
se.Message);
Console.WriteLine(se.Data);
Console.ReadLine();
}
}
public static void WriteObject(string path)
{
// Create a new instance of the Person class and
// serialize it to an XML file.
Person p1 = new Person("Mary", 1);
// Create a new instance of a StreamWriter
// to read and write the data.
FileStream fs = new FileStream(path,
FileMode.Create);
XmlDictionaryWriter writer = XmlDictionaryWriter.CreateTextWriter(fs);
DataContractSerializer ser =
new DataContractSerializer(typeof(Person));
ser.WriteObject(writer, p1);
Console.WriteLine("Finished writing object.");
writer.Close();
fs.Close();
}
public static void ReadObject(string path)
{
// Deserialize an instance of the Person class
// from an XML file. First create an instance of the
// XmlDictionaryReader.
FileStream fs = new FileStream(path, FileMode.OpenOrCreate);
XmlDictionaryReader reader =
XmlDictionaryReader.CreateTextReader(fs, new XmlDictionaryReaderQuotas());
// Create the DataContractSerializer instance.
DataContractSerializer ser =
new DataContractSerializer(typeof(Person));
// Deserialize the data and read it from the instance.
Person newPerson = (Person)ser.ReadObject(reader);
Console.WriteLine("Reading this object:");
Console.WriteLine(String.Format("{0}, ID: {1}",
newPerson.Name, newPerson.ID));
fs.Close();
}
}
}

Deserialisation doesn't rebuild dictionaries that are members of classes

I've got some serialisation code set up as follows:
static void SerialiseObject(Object o, String path)
{
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream(path, FileMode.Create);
formatter.Serialize(stream, o);
stream.Close();
}
static Object DeserialiseObject(String path)
{
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream(path, FileMode.Open, FileAccess.Read);
Object o = (Object)formatter.Deserialize(stream);
stream.Close();
return o;
}
And a class with the following member defined:
[Serializable]
public class CircuitModel
{
public Dictionary<String, Bus> Buses { protected set; get; }
...
}
I populate the Dictionary, and then the following code successfully serialises and deserialises the dictionary, with all Bus objects intact:
SerialiseObject(CircuitModel.Buses, "temp.bin");
Object o = DeserialiseObject("temp.bin");
But when I try to do the same for CircuitModel:
SerialiseObject(CircuitModel, "temp.bin");
Object o = DeserialiseObject("temp.bin");
CircuitModel.Buses has been initialised, but is empty.
I've also tried implementing serialisation with ISerializable (for the Bus and CircuitModel classes) and had exactly the same problem
Any idea as to why this would be happening?
I think you have something more sinister going on with your child collection because binary serialization of Dictionaries within classes does work just fine.
[TestFixture]
public class SerializeTest
{
[Test]
public void TestSer()
{
var parent = new Parent
{
Name = "Test"
};
parent.Children.Add("Child1", new Child {Name = "Child1"});
parent.Children.Add( "Child2", new Child { Name = "Child2" } );
SerialiseObject(parent, "test.bin");
var copy = DeserialiseObject("test.bin") as Parent;
Assert.IsNotNull(copy);
Assert.AreEqual(2, copy.Children.Count);
Assert.IsTrue(copy.Children.ContainsKey("Child1"));
Assert.AreEqual("Child1", copy.Children["Child1"].Name);
}
static void SerialiseObject( Object o, String path )
{
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream( path, FileMode.Create );
formatter.Serialize( stream, o );
stream.Close();
}
static Object DeserialiseObject( String path )
{
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream( path, FileMode.Open, FileAccess.Read );
Object o = (Object) formatter.Deserialize( stream );
stream.Close();
return o;
}
[Serializable]
private class Parent
{
public string Name { get; set; }
public Dictionary<string, Child> Children { get; protected set; }
public Parent()
{
Children = new Dictionary<string, Child>();
}
}
[Serializable]
private class Child
{
public string Name { get; set; }
}
}
The children deserialize with the parent and contain the details they were initialized with. I would check any code that is setting your Buses collection. My example just did it in the constructor of the parent class, but it may be possible that you have rogue code setting it after it's been deserialized?
Dictionaries are not serializable. Remove the dictionary if you need to serialize that data, and replace it by a list of a custom class that contains the data in the dictionary:
[Serializable]
public class BusItem
{
public string Name {get;set;}
public Bus Bus {get;set;}
}
Edit: I just found out you can actually serialize Dictionaries using the DataContractSerializer instead.
http://theburningmonk.com/2010/05/net-tips-xml-serialize-or-deserialize-dictionary-in-csharp/
If you are talking about XML serialization, it might be because Dictionary is not serializable to XML. Look at Why isn't there an XML-serializable dictionary in .NET.

Serializing/deserializing with memory stream

I'm having an issue with serializing using memory stream. Here is my code:
/// <summary>
/// serializes the given object into memory stream
/// </summary>
/// <param name="objectType">the object to be serialized</param>
/// <returns>The serialized object as memory stream</returns>
public static MemoryStream SerializeToStream(object objectType)
{
MemoryStream stream = new MemoryStream();
IFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, objectType);
return stream;
}
/// <summary>
/// deserializes as an object
/// </summary>
/// <param name="stream">the stream to deserialize</param>
/// <returns>the deserialized object</returns>
public static object DeserializeFromStream(MemoryStream stream)
{
IFormatter formatter = new BinaryFormatter();
stream.Seek(0, SeekOrigin.Begin);
object objectType = formatter.Deserialize(stream);
return objectType;
}
The error I'm getting is as follow:
stream is not a valid binary format. The starting contents (in bytes) are: blah....
I'm not exactly sure what is causing the error. Any help would be greatly appreciated.
Example of the call:
Dog myDog = new Dog();
myDog.Name= "Foo";
myDog.Color = DogColor.Brown;
MemoryStream stream = SerializeToStream(myDog)
Dog newDog = (Dog)DeserializeFromStream(stream);
This code works for me:
public void Run()
{
Dog myDog = new Dog();
myDog.Name= "Foo";
myDog.Color = DogColor.Brown;
System.Console.WriteLine("{0}", myDog.ToString());
MemoryStream stream = SerializeToStream(myDog);
Dog newDog = (Dog)DeserializeFromStream(stream);
System.Console.WriteLine("{0}", newDog.ToString());
}
Where the types are like this:
[Serializable]
public enum DogColor
{
Brown,
Black,
Mottled
}
[Serializable]
public class Dog
{
public String Name
{
get; set;
}
public DogColor Color
{
get;set;
}
public override String ToString()
{
return String.Format("Dog: {0}/{1}", Name, Color);
}
}
and the utility methods are:
public static MemoryStream SerializeToStream(object o)
{
MemoryStream stream = new MemoryStream();
IFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, o);
return stream;
}
public static object DeserializeFromStream(MemoryStream stream)
{
IFormatter formatter = new BinaryFormatter();
stream.Seek(0, SeekOrigin.Begin);
object o = formatter.Deserialize(stream);
return o;
}
Use Method to Serialize and Deserialize Collection object from memory. This works on Collection Data Types. This Method will Serialize collection of any type to a byte stream. Create a Seperate Class SerilizeDeserialize and add following two methods:
public class SerilizeDeserialize
{
// Serialize collection of any type to a byte stream
public static byte[] Serialize<T>(T obj)
{
using (MemoryStream memStream = new MemoryStream())
{
BinaryFormatter binSerializer = new BinaryFormatter();
binSerializer.Serialize(memStream, obj);
return memStream.ToArray();
}
}
// DSerialize collection of any type to a byte stream
public static T Deserialize<T>(byte[] serializedObj)
{
T obj = default(T);
using (MemoryStream memStream = new MemoryStream(serializedObj))
{
BinaryFormatter binSerializer = new BinaryFormatter();
obj = (T)binSerializer.Deserialize(memStream);
}
return obj;
}
}
How To use these method in your Class:
ArrayList arrayListMem = new ArrayList() { "One", "Two", "Three", "Four", "Five", "Six", "Seven" };
Console.WriteLine("Serializing to Memory : arrayListMem");
byte[] stream = SerilizeDeserialize.Serialize(arrayListMem);
ArrayList arrayListMemDes = new ArrayList();
arrayListMemDes = SerilizeDeserialize.Deserialize<ArrayList>(stream);
Console.WriteLine("DSerializing From Memory : arrayListMemDes");
foreach (var item in arrayListMemDes)
{
Console.WriteLine(item);
}
BinaryFormatter may produce invalid output in some specific cases. For example it will omit unpaired surrogate characters. It may also have problems with values of interface types. Read this documentation page including community content.
If you find your error to be persistent you may want to consider using XML serializer like DataContractSerializer or XmlSerializer.
It can be done easily by using System.Text.Json in .Net 6
using System.Text.Json;
Examlple ex = JsonSerializer.Deserialize<Example>(ms);
Console.WriteLine(ex.Value);
class Example
{
string Value {get; set; }
}
Refer to this for serialization.

How to serialize a collection of key:string, value:object using soapformatter

I need a collection of keys and values (like a dictionary) but it needs to be serializable using the Soapformatter.
Why the soapformatter?
I don't know the type that has to be serialized, I only know the interface that the type implements.
Does anyone have a clue how to crack this nut?
Apparently all it takes is inheriting from Hashtable and adding the following constructors:
[Serializable]
public class StateContainer : Hashtable, IStateContainer
{
public StateContainer() : base() { }
public StateContainer(SerializationInfo info, StreamingContext context) : base(info, context) { }
}
Took me half a day to figure this out...
you can then serialize this class like this:
XmlDocument xmlDocument = null;
using (MemoryStream memData = new MemoryStream())
{
SoapFormatter formatter = new SoapFormatter();
formatter.Serialize(memData, state);
memData.Flush();
memData.Position = 0;
xmlDocument = new XmlDocument();
xmlDocument.Load(memData);
}
And deserialize like this:
IStateContainer response = null;
using (MemoryStream memData = new MemoryStream())
{
using (StreamWriter writer = new StreamWriter(memData))
{
writer.Write(state.stateobject);
writer.Flush();
memData.Flush();
SoapFormatter formatter = new SoapFormatter();
memData.Position = 0;
response = (IStateContainer)formatter.Deserialize(memData);
}
}
Hope this can help someone else out there some day :-)

Categories