G
Guest
I'm trying to write a custom formatter. I'm using the .NET Framework's
ObjectManager class to do so, but I can't persuade the it to fixup object
references in a value type.
Some cut-down code that reproduces the problem I'm having is shown below.
Can anyone help me? (Is there anyone from Microsoft that can pass this to
someone who is familiar with the ObjectManager? Please?)
Thanks,
- Lee
using System;
using System.Runtime.Serialization;
namespace Test
{
class C1
{
static void Main()
{
// Pretend we're deserializing from a stream. We're aiming for:
//
// C2 root = new C2();
// root.m_s = new S();
// root.m_s.m_i = 100;
// root.m_s.m_o = new C3();
// root.m_s.m_o.m_i = 4;
// c2_info will be used to deserialize an instance of C2.
SerializationInfo c2_info = new SerializationInfo(typeof(C2), new
FormatterConverter());
S s = new S();
s.m_i = 100;
c2_info.AddValue("m_s", s); // Box the value type, s.
// c3_info will be used to deserialize an instance of C3
SerializationInfo c3_info = new SerializationInfo(typeof(C3), new
FormatterConverter());
c3_info.AddValue("m_i", 4);
// Build the object graph we're aming for using the
// SerializationInfo objects.
ObjectManager om = new ObjectManager(null, new
StreamingContext(StreamingContextStates.All, null));
// Create an empty C2 and register it.
object c2 = FormatterServices.GetUninitializedObject(typeof(C2));
om.RegisterObject(c2, 1, c2_info);
// Create an empty S and register it.
object boxed_s = c2_info.GetValue("m_s", typeof(S));
om.RegisterObject(boxed_s, 2, null, 1, null);
// I don't think the last parameter should be null, but I
// don't know what to set it to, baring in mind that C2
// implements ISerializable.
// Ask the ObjectManager to perform 'boxed_s.m_o = c3'
// assignment during fixup.
om.RecordFixup(2, typeof(S).GetField("m_o"), 3);
// Create an empty C3 and register it.
object c3 = FormatterServices.GetUninitializedObject(typeof(C3));
om.RegisterObject(c3, 3, c3_info);
Console.WriteLine("m_i = {0}, m_o = {1}", ((S)boxed_s).m_i,
((S)boxed_s).m_o == null ? "null" : "NOT null");
// m_i = 100, m_o = null
// This is correct: the fixup hasn't happend yet.
om.DoFixups();
Console.WriteLine("m_i = {0}, m_o = {1}", ((S)boxed_s).m_i,
((S)boxed_s).m_o == null ? "null" : "NOT null");
// m_i = 100, m_o = NOT null
// This is correct (or at least promising): the
// fixup has happened.
C2 root = (C2)om.GetObject(1);
Console.WriteLine("m_i = {0}, m_o = {1}", root.m_s.m_i, root.m_s.m_o ==
null ? "null" : "NOT null");
// m_i = 100, m_o = null
// But the fixup hasn't made it to the value type
// in the C2 instance registered as object #1.
// C2 is being completed before the boxed_s.m_o fixup,
// so the value copy in C2() is copying the unfixed-up object!
// What am I doing wrong!?
Console.ReadLine();
}
}
[Serializable]
class C2 : ISerializable
{
public S m_s;
C2(SerializationInfo info, StreamingContext context)
{
m_s = (S)info.GetValue("m_s", typeof(S));
}
public void GetObjectData(SerializationInfo info, StreamingContext
context)
{
// We don't need this as we're only deserializing, not serializing.
}
}
[Serializable]
struct S
{
public int m_i;
public object m_o;
}
[Serializable]
class C3 : ISerializable
{
public int m_i;
#region ISerializable Members
private C3(SerializationInfo info, StreamingContext context)
{
m_i = info.GetInt32("m_i");
}
public void GetObjectData(SerializationInfo info, StreamingContext
context)
{
// We don't need this as we're only deserializing, not serializing.
}
#endregion
}
}
ObjectManager class to do so, but I can't persuade the it to fixup object
references in a value type.
Some cut-down code that reproduces the problem I'm having is shown below.
Can anyone help me? (Is there anyone from Microsoft that can pass this to
someone who is familiar with the ObjectManager? Please?)
Thanks,
- Lee
using System;
using System.Runtime.Serialization;
namespace Test
{
class C1
{
static void Main()
{
// Pretend we're deserializing from a stream. We're aiming for:
//
// C2 root = new C2();
// root.m_s = new S();
// root.m_s.m_i = 100;
// root.m_s.m_o = new C3();
// root.m_s.m_o.m_i = 4;
// c2_info will be used to deserialize an instance of C2.
SerializationInfo c2_info = new SerializationInfo(typeof(C2), new
FormatterConverter());
S s = new S();
s.m_i = 100;
c2_info.AddValue("m_s", s); // Box the value type, s.
// c3_info will be used to deserialize an instance of C3
SerializationInfo c3_info = new SerializationInfo(typeof(C3), new
FormatterConverter());
c3_info.AddValue("m_i", 4);
// Build the object graph we're aming for using the
// SerializationInfo objects.
ObjectManager om = new ObjectManager(null, new
StreamingContext(StreamingContextStates.All, null));
// Create an empty C2 and register it.
object c2 = FormatterServices.GetUninitializedObject(typeof(C2));
om.RegisterObject(c2, 1, c2_info);
// Create an empty S and register it.
object boxed_s = c2_info.GetValue("m_s", typeof(S));
om.RegisterObject(boxed_s, 2, null, 1, null);
// I don't think the last parameter should be null, but I
// don't know what to set it to, baring in mind that C2
// implements ISerializable.
// Ask the ObjectManager to perform 'boxed_s.m_o = c3'
// assignment during fixup.
om.RecordFixup(2, typeof(S).GetField("m_o"), 3);
// Create an empty C3 and register it.
object c3 = FormatterServices.GetUninitializedObject(typeof(C3));
om.RegisterObject(c3, 3, c3_info);
Console.WriteLine("m_i = {0}, m_o = {1}", ((S)boxed_s).m_i,
((S)boxed_s).m_o == null ? "null" : "NOT null");
// m_i = 100, m_o = null
// This is correct: the fixup hasn't happend yet.
om.DoFixups();
Console.WriteLine("m_i = {0}, m_o = {1}", ((S)boxed_s).m_i,
((S)boxed_s).m_o == null ? "null" : "NOT null");
// m_i = 100, m_o = NOT null
// This is correct (or at least promising): the
// fixup has happened.
C2 root = (C2)om.GetObject(1);
Console.WriteLine("m_i = {0}, m_o = {1}", root.m_s.m_i, root.m_s.m_o ==
null ? "null" : "NOT null");
// m_i = 100, m_o = null
// But the fixup hasn't made it to the value type
// in the C2 instance registered as object #1.
// C2 is being completed before the boxed_s.m_o fixup,
// so the value copy in C2() is copying the unfixed-up object!
// What am I doing wrong!?
Console.ReadLine();
}
}
[Serializable]
class C2 : ISerializable
{
public S m_s;
C2(SerializationInfo info, StreamingContext context)
{
m_s = (S)info.GetValue("m_s", typeof(S));
}
public void GetObjectData(SerializationInfo info, StreamingContext
context)
{
// We don't need this as we're only deserializing, not serializing.
}
}
[Serializable]
struct S
{
public int m_i;
public object m_o;
}
[Serializable]
class C3 : ISerializable
{
public int m_i;
#region ISerializable Members
private C3(SerializationInfo info, StreamingContext context)
{
m_i = info.GetInt32("m_i");
}
public void GetObjectData(SerializationInfo info, StreamingContext
context)
{
// We don't need this as we're only deserializing, not serializing.
}
#endregion
}
}