2009-05-04 65 views
8

我有2个接口IA和IB。如何序列化具有接口作为属性的对象?

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

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

    void SetIA(IA value); 
} 

每个接口引用另一个接口。

我想按照下面的定义序列化ClassA。

[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; 
    } 
} 

当我尝试太序列化时,我得到一个错误,因为2个属性是接口。我想序列化属性。

我该如何解决这个问题?

我需要在每个接口中引用另一个接口。而且我需要能够来回地序列化课程。

回答

10

你在代码中有各种错误,否则这将工作得很好。

  1. ClassA的构造函数中,您正在设置局部变量IB,而不是对象的IB对象。
  2. ClassB中,您将转回到对象具体类,而不是将其作为接口类型单独保留。

这里是你的代码应该是什么样子:

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(); 
} 
+0

我修复了错误,它能够来回移动。 – 2009-05-04 20:31:50

+0

是的。很容易出现复制粘贴错误。很高兴这有助于。 – 2009-05-04 20:40:57

0

假设你不想序列化的接口属性,放置在接口属性如下属性

[NonSerialized] 

+1

我想序列化的属性。我已经重新提出了这个问题来反映这一点。 – 2009-05-04 20:13:05

+0

你可以用一个自定义的序列化器/解串器来做到这一点。在您的自定义序列化器中,您只需维护关于保存在接口属性中的对象的附加信息。 你也可以避免通过简单计数已经序列化/反序列化的循环引用。 – rein 2009-05-04 20:25:40

0

为了回答你的问题:还有两个问题。你是什​​么序列化?数据库引用是否可识别?

您不序列化接口;你序列化对象。您序列化的对象是IA或IB的实现。

由序列化对象决定是否应该序列化其中一个属性。如果属性需要序列化,它应该实现Serializable接口。

如果数据库能够识别序列化对象,那么您只能序列化由循环引用A < - > B形成的所谓“岛”:它应该首先为A分配空间,开始序列化A的属性。当它到达B时,它会发现它的一个属性是指A。序列化应包含对A的序列化版本的引用。

这很像两个熟人在同一时间搬家:首先他们会交换他们未来的地址,只有这样他们才会身体上移动。

2

你的对象实现了ISerializable来控制序列化。

[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); 
    } 
} 
-1

接口属性不可序列化。但是,引用这些属性的字段(在子类中)是。

你需要做这样的事情:

[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; 
    } 
} 
相关问题