RE: ObjectManager Problem - Plea for help!

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance

From: Lee Chapman (LeeChapman_at_newsgroup.nospam)
Date: 01/19/05


Date: Wed, 19 Jan 2005 03:19:03 -0800


Thanks very much for helping with this, but, unfortunately, I don't think
we're quite there yet.

> After some further consulting, our dev guys found that the following change
> can do the work:
>
> replacing
>
> ============
> object boxed_s = c2_info.GetValue("m_s", typeof(S));
>
> om.RegisterObject(boxed_s, 2, null, 1, null);
> ============
>
> with
>
> ==============
> object boxed_s = c2_info.GetValue("m_s", typeof(S));
>
> System.Reflection.MemberInfo[] m =typeof(C2).GetMember("m_s");
>
> om.RegisterObject(boxed_s, 2, null, 1, m[0]);
> om.DoFixups();
> ==============
>
> Since the boxed_s is member (m_s) of c2 , we need to specify the memberinfo
> in the 4th paramter

I think your dev guys may have missed the point I was trying to make in the
C# comments. I didn't think that the 4th parameter to RegisterObject() was
supposed to be null, but I don't think it can be an expression based on the
name of one of C2's fields. This is because C2 implements ISerializable. Let
me expand upon that.

You are suggesting that, because S is value-type (a struct), when I register
an instance of S with the ObjectManager, the 4th parameter to
RegisterObject() should be - as the documentation for RegisterObject says -
"the field in the containing object where S exists". To do this I can, as you
have suggested, try to use Type.GetMember(), or even Type.GetField():

om.RegisterObject(boxed_s, 2, null, 1, typeof(C2).GetField("m_s"));

The problem is that during deserialization I don't know that C2.m_s is the
containing field. I know that boxed_s belongs in a specific instance of C2,
yes, but I don't know that it is the m_s field. As I've said, this is because
C2 implements ISerializable: the GetObjectData() method and the custom
constructor required for custom serialization allows there to be a level of
indirection between an object's field and the name that field's data is
serialized under. For example:

[Serializable]
class C2 : ISerializable
{
  public S m_s;

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

  public void GetObjectData(SerializationInfo info, StreamingContext context)
  {
    info.AddValue("ArbitraryName", m_s);
  }
}

So now, the formatter code would need to change to:

object boxed_s = c2_info.GetValue("ArbitraryName", typeof(S));
om.RegisterObject(boxed_s, 2, null, 1, typeof(C2).GetField("m_s"));

But where do I get the string "m_s" from? As far as the formatter knows,
this field is known as "ArbitraryName", not the actual field name, "m_s".
(During deserialization of an instance of C2, the formatter could enumerate
the SerializationInfo object extracted from the underlying stream via
SerializationInfo.GetEnumerator(), but it would find the name
"ArbitraryName", not "m_s".) As far as I can see, the only link between these
two strings is in the code for ISerializable.GetObjectData() and the custom
constructor, which I - as the author of the formatter, not the objects it
deserializes - have no control over.

Does that make sense?

The second problem I have is with calling DoFixups() more than once. The
solution you are proposing involves calling DoFixups() as soon as boxed_s is
registered with the ObjectManager, but I can't guarantee that at this point
in time the ObjectManager will have had all referenced objects registered
with it.

For example, if we ignore the m_s problem for a moment and I record a fixup
on a totally different object before I even encounter C2 then the code
becomes:

om.RegisterObject(new C4(), 4);
om.RecordFixup(4, typeof(C4).GetField("whatever"), 5);

object boxed_s = c2_info.GetValue("m_s", typeof(S));
om.RegisterObject(boxed_s, 2, null, 1, typeof(C2).GetField("m_s"));
om.DoFixups();

And the call to DoFixups() generates an exception: "The object with ID 5 was
referenced in a fixup but does not exist."

For completeness, C4 is defined as:

[Serializable]
class C4
{
  public object whatever;
}

and the deserialization stream would eventually yield:

om.RegisterObject(new C4(), 5);

(I appreciate that in this example, there is no explicit link between the
instances of C4 and the other objects in the graph, but there easily could
be: C2 could have another field, m_c4.)

> Also, after the change, you'll found that your second test statement
> =====================
> ((S)boxed_s).m_o == null
> =====================
>
> will always return true which means the boxed_s 's m_o is null. And the dev
> guy think this was because once we specify S (objid 2) as a child of
> C2(Objid 1) then any Fixup on the S is directly happening on C2¡¯s child S
> and the boxed_s 's "m_o" won't be set to c3(object id =3).

Yes, that makes sense - at least for containing objects that don't implement
ISerializable. I'm not sure it makes sense to me for containing objects that
do implement ISerializable.

> In addition, it seems that there hasn't been any detailed reference or
> documtation on manually deserializing via the ObjectManager class since its
> internal mechanism is hidden from us.

Doh. Okay, where do we go from here then?

Thanks,
- Lee



Relevant Pages

  • serialization inherited objects
    ... deserialization. ... Some extra propertys in the objects ... Now I would like some solution will the serialization keeps working. ... that in my app I would like to keep using my original name ...
    (microsoft.public.dotnet.languages.vb)
  • Re: cannot use static fields in AJAX applications?
    ... type's assembly is sufficient to resolve additional types. ... serializer construction for specific types. ... ViewState's built-in serialization does not like dynamically constructed ... serializers for later deserialization requests. ...
    (microsoft.public.dotnet.framework.aspnet)
  • Re: Serialization woes
    ... > serialization of an object (i.e. by implementing the ... > object and the call to the special constructor. ... its elements *until* deserialization is complete - ... aknak at aksoto dot idps dot co dot uk ...
    (microsoft.public.dotnet.languages.vb)
  • Re: calling methods on deserialized objects
    ... serialization and deserialization breaks the internal connection between hashes and their associated classes, ... What "internal connection" are you refering to? ... The serialized structure looks good (I had a look at the session text file), references are replaced by their serialized target, no memory address pointers inside ... ... respective classes after deserialization, ...
    (comp.lang.perl.modules)