2009-05-04 14 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

私はバグを修正し、前後に行くことができました。 –

+0

うん。コピー・ペーストのエラーになるのは簡単です。これはうれしかったです。 –

0

あなたがインターフェイスプロパティをシリアル化したくないと仮定すると、インターフェイスのプロパティで、次の属性

[NonSerialized] 

を配置します。

+1

私はプロパティをシリアル化したいです。私はそれを反映するために質問に言い直しました。 –

+0

カスタムシリアライザ/デシリアライザでこれを実行できます。カスタムシリアライザでは、インターフェイスプロパティに保持されているオブジェクトに関する追加情報を単純に維持します。 既にシリアライズ/デシリアライズしたものを簡単にカウントすることで、間違いなく循環参照を避けることもできます。 – rein

0

あなたの質問の答え:他の2つの質問。あなたは何をシリアライズしますか?データベースは参照を認識していますか?

インターフェイスをシリアル化しません。オブジェクトをシリアル化します。シリアル化するオブジェクトは、IAまたはIBの実装のいずれかです。

プロパティのシリアル化が必要かどうかは、シリアル化されたオブジェクトによって決まります。プロパティにシリアライズする必要がある場合は、Serializableインターフェイスを実装する必要があります。

データベースがシリアル化されたオブジェクトを識別できる場合は、円参照A< - > Bで形成された、いわゆるアイランドのみをシリアル化できます。まずAのスペースを割り当て、Aのプロパティのシリアル化を開始する必要があります。 Bに到着すると、Aを参照するプロパティが見つかります。シリアライゼーションには、シリアル化されたバージョンのリファレンスが含まれています。

これは、2人の知人が同じ時間に家を動かすのと同じです。彼らの将来のアドレスを交換してください、そして、彼らは物理的に移動します。

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

ClassAへの変更は、読者の練習として残されています。 :) これはほとんど同じことです。 – Greg

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

オブジェクトグラフのシリアル化に問題はありませんでした。そのインターフェイスのプロパティはどこでシリアライズできないのですか?また、自動不動産がうまく動作するのはなぜですか? –

+0

これは、シリアライズ可能であるかどうかの基本的な誤解(私の側で)によるものです。 (私はそれを間違ってやってきました。)インターフェースは直列化できません。インターフェイスから派生したクラスのプロパティは直列化可能です。それを指摘してくれてありがとう。 –

関連する問題