Home All Groups Group Topic Archive Search About

Custom Formatter - ValueType ISerializable Deserialization Problem

Author
13 Jan 2005 3:27 AM
Lee Chapman
I'm trying to write a custom formatter. I'm utilising the ObjectManager
class, but I can't persuade fixups to work properly with structs. What am I
doing wrong?

The first call to Test() works as expected: c.s.o ends up as a boxed
integer. The second call doesn't work: c.s.o is left as null rather than as
the expected boxed integer. The only difference between the two calls is
that the first one is emulating using reflection to deserialize the class
(C1) and the second call is using custom serialization (via ISerializable)
to emulate deserializing the class.

This code is a self-contained, cut down version that demonstrates the
problem I'm having. I want to know why the SerializationInfo object that is
passed to the C2 constructor hasn't been fixed-up with the fixup recorded in
the om.RecordFixup(2, so_mi, 4) call.

[Class1.cs]

using System;
using System.Reflection;
using System.Runtime.Serialization;

namespace Test
{
class Class1
{
  static MemberInfo so_mi = typeof(S).GetMember("o")[0];

  static void Main()
  {
   object c;

   c = Test(typeof(C1), null);

   // c.s.o == {4}

   SerializationInfo info = new SerializationInfo(c.GetType(), new
FormatterConverter());
   info.AddValue("s", new S());
   c = Test(typeof(C2), info);

   // c.s.o != {4}
  }

  static S s;

  static object Test(Type type, SerializationInfo info)
  {
   ObjectManager om = new ObjectManager(null, new
StreamingContext(StreamingContextStates.All, null));

   object c = FormatterServices.GetUninitializedObject(type);
   om.RegisterObject(c, 1, info);

   MemberInfo m = type.GetField("s");
   om.RegisterObject(new S(), 2, null, 1, m);

   om.RecordFixup(2, so_mi, 4);

   om.RegisterObject((object)4, 4);

   om.DoFixups();

   return om.GetObject(1);
  }
}

class C1
{
  public S s;
}

class C2 : ISerializable
{
  public S s;

  C2(SerializationInfo info, StreamingContext context)
  {
   s = (S)info.GetValue("s", typeof(S));
  }

  public void GetObjectData(SerializationInfo info, StreamingContext
context)
  {
  }
}

struct S
{
  public object o;
}
}

[attached file: Class1.cs]

Author
13 Jan 2005 2:12 PM
Lee Chapman
The line

    SerializationInfo info = new SerializationInfo(c.GetType(), new
FormatterConverter());

should have been

    SerializationInfo info = new SerializationInfo(typeof(C2), new
FormatterConverter());

And I think I've worked out what I'm doing wrong: if I also register the
value type as a delayed fixup then the code appears to work.

static object Test(Type type, SerializationInfo info)
{
ObjectManager om = new ObjectManager(null, new
StreamingContext(StreamingContextStates.All, null));

object c = FormatterServices.GetUninitializedObject(type);
om.RegisterObject(c, 1, info);

if (info != null)
  om.RecordDelayedFixup(1, "s", 2);

om.RegisterObject(new S(), 2, null, 1, null);
om.RecordFixup(2, s.GetType().GetField("o"), 4);

om.RegisterObject((object)4, 4);

om.DoFixups();

return om.GetObject(1);
}

AddThis Social Bookmark Button