I want to serialize/deserialize an object that has been instantiated by another object loaded from an assembly:
Interfaces.cs (from a referenced assembly, Interfaces.dll)
public interface ISomeInterface
{
ISettings Settings { get; set; }
}
public interface ISettings : ISerializable
{
DateTime StartDate { get; }
}
SomeClass.cs (from a referenced assembly, SomeClass.dll)
public class SomeClass : ISomeInterface
{
private MySettings settings = new Settings();
public ISettings Settings
{
get { return (ISettings)settings; }
set { settings = value as MySettings; }
}
}
[Serializable]
public class MySettings : ISettings
{
private DateTime dt;
public MySettings() { dt = DateTime.Now; }
protected MySettings(SerializationInfo info, StreamingContext context)
{
dt = info.GetDateTime("dt");
}
[SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("dt", dt);
}
public DateTime StartDate
{
get { return startFrom; }
internal set { startFrom = value; }
}
}
Startup project:
[Serializable]
public class ProgramState
}
public ISettings Settings { get; set; }
}
In the startup project, eventually I set Settings of an instance of ProgramState to Settings of SomeClass. I then go on to do the serialization using:
public void SerializeState(string filename, ProgramState ps)
{
Stream s = File.Open(filename, FileMode.Create);
BinaryFormatter bFormatter = new BinaryFormatter();
bFormatter.Serialize(s, ps);
s.Close();
}
This doesn't throw any exceptions. I deserialize with:
public ProgramState DeserializeState(string filename)
{
if (File.Exists(filename))
{
ProgramState res = new ProgramState();
Stream s = File.Open(filename, FileMode.Open);
BinaryFormatter bFormatter = new BinaryFormatter();
try
{
res = (ProgramState)bFormatter.Deserialize(s);
}
catch (SerializationException se)
{
Debug.WriteLine(se.Message);
}
s.Close();
return res;
}
else return new ProgramState();
}
This throws an exception and the following appears in my Debug output:
A first chance exception of type 'System.Runtime.Serialization.SerializationException' occurred in mscorlib.dll
Unable to find assembly 'SomeClass, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
I'm sure that the assembly containing SomeClass has been loaded before the call to DeserializeState, so why is it throwing an exception that it is unable to find it?
I've been looking at some tutorials, but the ones I was able to find only deal with classes from the same assembly (plus, my understanding of the serialization and deserialization process in .NET is minimal - a link to a detailed explanation might be helpful).
In the meantime, is there any way to make this correctly deserialize the MySettings object?
After poking around some more (i.e. googling the answer), I was able to resolve this. Here is the modified code:
Interfaces.cs (from a referenced assembly, Interfaces.dll)
public interface ISomeInterface
{
ISettings Settings { get; set; }
}
public interface ISettings
{
DateTime StartDate { get; }
}
SomeClass.cs (from a referenced assembly, SomeClass.dll)
public class SomeClass : ISomeInterface
{
private MySettings settings = new Settings();
public ISettings Settings
{
get { return (ISettings)settings; }
set { settings = value as MySettings; }
}
}
[Serializable]
public class MySettings : ISettings
{
private DateTime dt;
public MySettings() { dt = DateTime.Now; }
public DateTime StartDate
{
get { return startFrom; }
internal set { startFrom = value; }
}
}
Serialization is done with:
public void SerializeState(string filename, ProgramState ps)
{
Stream s = File.Open(filename, FileMode.Create);
BinaryFormatter bFormatter = new BinaryFormatter();
bFormatter.AssemblyFormat =
System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;
bFormatter.Serialize(s, ps);
s.Close();
}
And deserialization with:
public ProgramState DeserializeState(string filename)
{
if (File.Exists(filename))
{
ProgramState res = new ProgramState();
Stream s = File.Open(filename, FileMode.Open);
BinaryFormatter bFormatter = new BinaryFormatter();
bFormatter.AssemblyFormat =
System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;
bFormatter.Binder = new MyBinder(); // MyBinder class code given below
try
{
res = (ProgramState)bFormatter.Deserialize(s);
}
catch (SerializationException se)
{
Debug.WriteLine(se.Message);
}
s.Close();
return res;
}
else return new ProgramState();
}
This class was added. This is the binder for the binary formatter:
internal sealed class MyBinder : SerializationBinder
{
public override Type BindToType(string assemblyName, string typeName)
{
Type ttd = null;
try
{
string toassname = assemblyName.Split(',')[0];
Assembly[] asmblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (Assembly ass in asmblies)
{
if (ass.FullName.Split(',')[0] == toassname)
{
ttd = ass.GetType(typeName);
break;
}
}
}
catch (System.Exception e)
{
Debug.WriteLine(e.Message);
}
return ttd;
}
}
Do you want to (de)serialize using binary format? If no you may use the following:
P.S. This is not an solution but some kind of workaround.
Some assembly
public interface ISomeInterface { ISettings Settings { get; set; } }
public interface ISettings : ISerializable
{
DateTime StartDate { get; }
}
public class SerializeHelper<T>
{
public static void Serialize(string path, T item)
{
var serializer = new XmlSerializer(typeof(T));
using (TextWriter textWriter = new StreamWriter(path, false, Encoding.UTF8))
{
serializer.Serialize(textWriter, T item);
}
}
}
SerializeHelper.Serialize(@"%temp%\sample.xml", instanceOfISomeInterface);
Some other assembly
public interface ISomeOtherInterface
{
ISettings Settings { get; set; }
}
public class DeSerializeHelper<T>
{
public static T Deserialize(string path)
{
T instance = default(T);
var serializer = new XmlSerializer(typeof(TestData));
using (TextReader r = new StreamReader(path, Encoding.UTF8))
{
instance = (T)serializer.Deserialize(r);
}
return instance;
}
}
ISomeOtherInterface instance = DeSerializeHelper.Deserialize<SomeOtherInterfaceImplementation>(@"%temp%\sample.xml")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With