views:

298

answers:

5

I have a question about binary serialization in C#

I need to be able to deep clone objects of class B (along with all it's subobjects in the graph of course). I'd like to implement this by using binary serialization. The discussion if that's the best method is irrelevant in the context of this question.

Say I have this class structure:

public class A 
{
    private B objB;
}

[Serializable]
public class B : ICloneable
{
    private C objC1;
    private C objC2;

    public object Clone()
    {
        B clone = Helper.Clone<B>(this);
        return (B)clone;
    }
}

[Serializable]
public class C
{
    int a;
    int b;
}

The helper class for deep cloning with binary serialization (I got this method code from somewhere on the net, don't really remember where TBH, but it looks alright)

public static class Helper
{
    public static T Clone<T>(T OriginalObject)
    {
        using (Stream objectStream = new MemoryStream())
        {
            IFormatter formatter = new BinaryFormatter();
            formatter.Serialize(objectStream, OriginalObject);
            objectStream.Seek(0, SeekOrigin.Begin);
            return (T)formatter.Deserialize(objectStream);
        }
    }

}

So at some point in my app, I hit following code:

B clone = (B)objA.objB.Clone();

The problem is that the debugger moans about class A not being marked as Serializable.

But I don't want to serialize A, I want to serialize B and it's subobject C.

I guess it tries to serialize the parent object A too, because it's all interconnected in the object graph. But is there any way I can exclude it from being serialized at this point?

+1  A: 

If B does not hold any reference to A, serializing B will not require A to be serializable even if A has a reference to B.

From your code sample, B does not hold any reference to A so it should work. Are you sure that the code sample you provided really represent your real scenario?

SelflessCoder
A: 

Im not sure, but what if you mark it as nonserializable? I'd test that :P

Francisco Noriega
tried it, but marking a class a nonserializable is not allowed, only fields
tjeuten
+1  A: 

This quick mock code works perfectly fine, your problem is elsewhere, perhaps C has variable of class A ?

public class A
{
    private B bObj = new B();

    public A()
    {
        B copy = bObj.Clone() as B;
    }
}
[Serializable]
public class B : ICloneable
{
    private int test = 10;

    public object Clone()
    {
        return Helper.Clone(this);
    }

}

EDIT per comment:

please add the following to your event in B

[field:NonSerialized]

This will prevent serialization of the invocation list of the event which in turn references A

Stan R.
I double checked, there is no reference either from B to A or from C to A ...The one thing there is, is that B contains a public event field, which an eventhandler in A listens to. Could this be the cause ?
tjeuten
@tjeuten, yes it is the case, event is trying to serialize the invocation list. please look at my edited answer
Stan R.
thx a zillion that did the trick !
tjeuten
A: 

There must be something else in play here - your code compiles and executes without issue (as it should - type A is not a part of type B's object graph).

Is it possible that objB is actually an instance of type A?

Andrew Hare
A: 

Ok thanks for all the replies, I did find the issue ...

Class B contains a public event field, and an eventhandler in Class A is subscribed to it. If I unsubscribe the eventhandler, serialization works.

My mistake for not posting the entire code situation, sorry :(

tjeuten