views:

708

answers:

6

I have 2 interfaces IA and IB.

public interface IA
{
    IB InterfaceB { get; set;  }
}

public interface IB
{
    IA InterfaceA { get; set;  }

    void SetIA(IA value);
}

Each interfaces references the other.

I am trying to serialize ClassA as defined below.

[Serializable]
public class ClassA : IA
{
    public IB InterfaceB { get; set; }

    public ClassA()
    {
        // Call outside function to get Interface B
        IB interfaceB = Program.GetInsanceForIB();

        // Set IB to have A
        interfaceB.SetIA(this);
    }
}

[Serializable]
public class ClassB : IB
{
    public IA InterfaceA { get; set; }

    public void SetIA(IA value)
    {
        this.InterfaceA = value as ClassA;
    }
}

I get an error when I try too serialize because the 2 properties are interfaces. I want to serialize the properties.

How would I get around this?

I need to have references in each interface to the other. And I need to be able to serialize the class back and forth.

A: 

Assuming you don't want to serialize the interface property, place the following attribute

[NonSerialized]

on the interface property.

rein
I do want to Serialize the properties. I have reworded the question to reflect that.
David Basarab
You could do this with a custom serializer/deserializer. In your custom serializer you would simply maintain added information about the object which is held in the interface property.You could also avoid the circular reference which there no doubt would be by maintaining a simple count of what you have serialized/deserialized already.
rein
A: 

In return for your question: two other questions. What do you Serialize? Is the database reference-aware?

You don't serialize interfaces; you serialize objects. The object you serialize is either an implementation of IA or IB.

It's up to the serialized object to decide whether one of it's properties should be serialized or not. If the property does need serializing, it should implement the Serializable interface.

You can only serialize a so called 'island' formed by a circular reference A <-> B if the database can identify the serialized objects: it should first 'allocate' space for A, start serializing A's properties. When it arrives at B, it will find one of it's properties referring to A. The serialization should then include a reference to the serialized version of A.

It's much like two acquaintances moving houses at the same time: first they will exchange their future adresses, only then they will physically move.

xtofl
+4  A: 

You have various bugs in your code, otherwise this would work just fine.

  1. In the constructor for ClassA, your are setting an local variable IB, not the object's IB object.
  2. In ClassB, you are casting back to the object concrete class, instead of leaving it alone as the interface type.

Here is what your code should look like:

public interface IA 
{ 
    IB InterfaceB { get; set; } 
}

public interface IB 
{ 
    IA InterfaceA { get; set; } 
    void SetIA(IA value);
}

[Serializable]
public class ClassA : IA
{    
    public IB InterfaceB { get; set; }    

    public ClassA()    
    {        
        // Call outside function to get Interface B        
        this.InterfaceB = new ClassB();

        // Set IB to have A        
        InterfaceB.SetIA(this);    
    }
}

[Serializable]
public class ClassB : IB
{    
    public IA InterfaceA { get; set; }    

    public void SetIA(IA value)    
    {       
        this.InterfaceA = value;    
    }
}

[STAThread]
static void Main()
{
    MemoryStream ms = new MemoryStream();
    BinaryFormatter bin = new BinaryFormatter();

    ClassA myA = new ClassA();

    bin.Serialize(ms, myA);

    ms.Position = 0;

    ClassA myOtherA = bin.Deserialize(ms) as ClassA;


    Console.ReadLine();
}
Erich Mirabal
I fixed the bugs and it was able to go back and forth.
David Basarab
Yeah. It's easy to get to the copy-paste errors. Glad this helped.
Erich Mirabal
A: 

Implement ISerializable on your objects to control the serialization.

[Serializable]
public class ClassB : IB, ISerializable
{
  public IA InterfaceA { get; set; }

  public void SetIA(IA value)
  {
     this.InterfaceA = value as ClassA;
  }

  private MyStringData(SerializationInfo si, StreamingContext ctx) {
    Type interfaceAType = System.Type.GetType(si.GetString("InterfaceAType"));
    this.InterfaceA = si.GetValue("InterfaceA", interfaceAType);
  }

  void GetObjectData(SerializationInfo info, StreamingContext ctx) {
    info.AddValue("InterfaceAType", this.InterfaceA.GetType().FullName);
    info.AddValue("InterfaceA", this.InterfaceA);
  }
}
Greg
Changes to ClassA are left as an exercise to the reader. :)It's pretty much the same thing.
Greg
A: 

Interface properties are not serializable. However, fields that reference those properties (in the subclass) are.

You'll need to do something like this:

[Serializable]
public class ClassA : IA
{
    private IB _interfaceB;
    public IB InterfaceB { get { return _interfaceB; } set { _interfaceB = value; } }

    public ClassA()
    {
        // Call outside function to get Interface B
        IB interfaceB = Program.GetInsanceForIB();

        // Set IB to have A
        interfaceB.SetIA(this);
    }
}

[Serializable]
public class ClassB : IB
{
    private IA _interfaceA;
    public IA InterfaceA { get { return _interfaceA; } set { _interfaceA = value; } }

    public void SetIA(IA value)
    {
        this.InterfaceA = value as ClassA;
    }
}
Michael Todd
I had no problem serializing the object graph. Where do you get that interface properties are not serializable? Also, why have the private instace when the automatic property works just fine?
Erich Mirabal
Oops. This was due to a fundamental misunderstanding (on my part) of what is and is not serializable. (I've been doing it wrong all along.) Interfaces are NOT serializable; properties in a class derived from an interface ARE serializable. Thanks for pointing that out.
Michael Todd
A: 
[Serializable]
public class A
{
    private object obj;
    public object Obj
    {
        get{return obj;}
        set{obj=value;} 
    }

    public A(){}
    public A(object obj)
    {
        this.obj = obj;
    }
}

public class MySerialize
{
    public void SerializeData(A objSerialize)
    {

        TextWriter tw = new StreamWrite("myfile.xml");
        XmlSerializer seri = new XmlSerializer(objSerialize.GetType());
        seri.Serialize(tw,seri);
    }
}

A a = new A(new object[1]{"abcdefg"});
MySerialize mySerialize = new MySerialize();
mySerialize.SerializeData(a);

When program ran --> it could not serialize. An exception occurs: There was an error generating the XML document.

Anyone knows that issue and have a solution for solve it. Please help me. Thank very much

This is a question not an answer. I would suggest asking a new question. Most likely here nobody will see it or answer it.
David Basarab