2009-05-04 6 views
8

J'ai 2 interfaces IA et IB.Comment puis-je sérialiser un objet possédant une interface en tant que propriété?

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

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

    void SetIA(IA value); 
} 

Chaque interface fait référence à l'autre.

J'essaie de sérialiser ClassA comme défini ci-dessous.

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

je reçois une erreur lorsque je tente trop sérialisation car les 2 propriétés sont des interfaces. Je veux sérialiser les propriétés.

Comment est-ce que je pourrais contourner ceci?

Je dois avoir des références dans chaque interface à l'autre. Et je dois être capable de sérialiser la classe d'avant en arrière.

Répondre

10

Vous avez plusieurs bugs dans votre code, sinon cela fonctionnerait très bien.

  1. Dans le constructeur pour ClassA, vous définissez une variable locale IB, pas l'objet IB de l'objet.
  2. Dans ClassB, vous renvoyez la classe concrète de l'objet au lieu de la laisser seule comme type d'interface.

Voici ce que votre code devrait ressembler à:

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

J'ai corrigé les bugs et il était capable d'aller et venir. –

+0

Oui. Il est facile d'accéder aux erreurs de copier-coller. Glad cela a aidé. –

0

En supposant que vous ne voulez pas sérialiser la propriété d'interface, placez l'attribut suivant

[NonSerialized] 

sur la propriété d'interface.

+1

Je ne veux sérialiser les propriétés. J'ai reformulé la question pour refléter cela. –

+0

Vous pouvez le faire avec un sérialiseur/désérialiseur personnalisé. Dans votre sérialiseur personnalisé, vous conserverez simplement des informations supplémentaires sur l'objet contenu dans la propriété d'interface. Vous pourriez également éviter la référence circulaire qui serait sans aucun doute en maintenant un compte simple de ce que vous avez déjà sérialisé/désérialisé. – rein

0

En échange de votre question: deux autres questions. Qu'est-ce que vous sérialiser? La base de données est-elle sensible à la référence?

Vous ne sérialisez pas les interfaces; vous sérialisez des objets. L'objet que vous sérialisez est une implémentation de IA ou IB.

Il appartient à l'objet sérialisé de décider si l'une de ses propriétés doit être sérialisée ou non. Si la propriété doit être sérialisée, elle doit implémenter l'interface Serializable.

Vous pouvez uniquement sérialiser un 'îlot' formé par une référence circulaire A < -> B si la base de données peut identifier les objets sérialisés: elle doit d'abord 'allouer' de l'espace A, commencer à sérialiser les propriétés. Quand il arrivera à B, il trouvera l'une de ses propriétés se référant à A. La sérialisation devrait alors inclure une référence à la version sérialisée de A.

C'est un peu comme deux connaissances qui déménagent des maisons en même temps: d'abord ils vont échanger leurs futures adresses, seulement alors ils vont bouger physiquement.

2

Mettre en oeuvre ISerializable sur vos objets pour contrôler la sérialisation.

[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

Les modifications de ClassA sont laissées au lecteur en tant qu'exercice. :) C'est à peu près la même chose. – Greg

-1

propriétés d'interface ne sont pas sérialisables. Cependant, les champs qui font référence à ces propriétés (dans la sous-classe) sont.

Vous aurez besoin de faire quelque chose comme ceci:

[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

Je n'ai eu aucun problème sérialisant le graphe d'objet. Où obtenez-vous que les propriétés de l'interface ne sont pas sérialisables? Aussi, pourquoi avoir l'institution privée quand la propriété automatique fonctionne bien? –

+0

Oups. Cela était dû à un malentendu fondamental (de ma part) de ce qui est et n'est pas sérialisable. (Je l'ai fait mal tout le long.) Les interfaces ne sont pas sérialisables; propriétés dans une classe dérivée d'une interface ARE sérialisable. Merci d'avoir fait remarquer cela. –

Questions connexes