0

J'essaye de programmer un logiciel domotique. En ce moment j'ai les classes suivantes:C# Echec du chargement du fichier sérialisé - Propriété de classe i: type

-Accueil
-Room
-Device
-WindowShutter (Hérite de l'appareil)
-Capteur (Hérite de l'appareil)

Actuellement l'objet Accueil, qui contient des pièces (qui contient des périphériques) est enregistré en XML.

public static async void SaveHome(Home MyHome) 
     { 
      MemoryStream _MemoryStream = new MemoryStream(); 
      DataContractSerializer Serializer = new DataContractSerializer(typeof(Home)); 
      Serializer.WriteObject(_MemoryStream, MyHome); 

      StorageFile _File = await ApplicationData.Current.LocalFolder.CreateFileAsync("Home2.bin", CreationCollisionOption.ReplaceExisting); 

      using (Stream fileStream = await _File.OpenStreamForWriteAsync()) 
      { 
       _MemoryStream.Seek(0, SeekOrigin.Begin); 
       await _MemoryStream.CopyToAsync(fileStream); 
       await fileStream.FlushAsync(); 
       fileStream.Dispose(); 
      } 
     } 

En raison des différents types de périphériques, le fichier enregistré ressemble à ceci:

<Home xmlns="http://schemas.datacontract.org/2004/07/CSRedAlert.Core.Classes" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> 
<Name>My Home</Name> 
<Rooms> 
<Room><Color/><Devices><Device><I2C_Slave_Address>64</I2C_Slave_Address><Id>0</Id><ImagePath i:nil="true"/><Name>My Device</Name><Pin>D0</Pin></Device> 
<Device i:type="WindowShutter"><I2C_Slave_Address>64</I2C_Slave_Address><Id>1</Id><ImagePath i:nil="true"/><Name>My Window Shutter</Name><Pin>D0</Pin><SecondaryPin>D1</SecondaryPin></Device> 
<Device i:type="Sensor"><I2C_Slave_Address>64</I2C_Slave_Address><Id>2</Id><ImagePath i:nil="true"/><Name>My Sensor</Name><Pin>A2</Pin></Device></Devices><I2C_SlaveAdress>64</I2C_SlaveAdress> 
<Name>Room</Name></Room></Rooms></Home> 

Le problème est, dès que je lance le programme une deuxième fois et le fichier Home2.bin est chargé , je reçois l'erreur suivante:

Aggregate Exception

Ceci est la méthode, qui charge le fichier:

J'ai compris, que le fichier sera chargé lorsque je supprime la propriété i: type du périphérique Elements dans le fichier Home2.bin. Mais quand je l'efface, les appareils vont perdre leur type et ne fonctionneront pas comme prévu.

Avez-vous une idée pour résoudre ce problème?

+1

Nouveau pour voir la définition des classes. Les instructions de pseudo-opérations au-dessus de la définition des classes et des propriétés doivent être définies correctement, de sorte que la sérialisation et la sérialisation fonctionnent toutes les deux. Assurez-vous que si vous êtes des applications de remorquage (une pour la sérialisation et l'autre pour la sérialisation), les deux sont mises à jour lorsque des modifications sont apportées aux classes. – jdweng

+0

Lorsque vous obtenez une exception AggregateException, la première chose que vous devez faire est de vérifier la [InnerException] (https://msdn.microsoft.com/en-us/library/system.aggregateexception.innerexceptions (v = vs.110). aspx) propriété. –

Répondre

0

La raison pour laquelle vous voyez cette exception est que DataContractSerializer requiert que tous les types qu'il rencontre pendant la sérialisation soient détectables de manière statique à l'avance via la réflexion. S'il rencontre un type inattendu - y compris une sous-classe de type polymorphe - il lance une exception.

Pour les types polymorphes, vous pouvez informer le sérialiseur des sous-types attendus en utilisant [KnownTypeAttribute]. Une fois cela fait, l'attribut "{http://www.w3.org/2001/XMLSchema-instance}type" indiquera le nom du contrat réel qui a été sérialisé.

Ainsi vos classes devraient ressembler à:

[DataContract(Namespace = "http://schemas.datacontract.org/2004/07/CSRedAlert.Core.Classes")] 
[KnownType(typeof(WindowShutter))] 
[KnownType(typeof(Sensor))] 
public class Device 
{ 
    [DataMember] 
    public int I2C_Slave_Address { get; set; } 

    [DataMember] 
    public int Id { get; set; } 

    [DataMember] 
    public string ImagePath { get; set; } 

    [DataMember] 
    public string Name { get; set; } 

    [DataMember] 
    public string Pin { get; set; } 
} 

[DataContract(Namespace = "http://schemas.datacontract.org/2004/07/CSRedAlert.Core.Classes")] 
public class WindowShutter : Device 
{ 
    [DataMember] 
    public string SecondaryPin { get; set; } 
} 

[DataContract(Namespace = "http://schemas.datacontract.org/2004/07/CSRedAlert.Core.Classes")] 
public class Sensor : Device 
{ 
} 

[DataContract(Namespace = "http://schemas.datacontract.org/2004/07/CSRedAlert.Core.Classes")] 
public class Home 
{ 
    [DataMember] 
    public string Name { get; set; } 

    [DataMember] 
    public List<Room> Rooms { get; set; } 
} 

[DataContract(Namespace = "http://schemas.datacontract.org/2004/07/CSRedAlert.Core.Classes")] 
public class Room 
{ 
    [DataMember] 
    public string Color { get; set; } 

    [DataMember] 
    public List<Device> Devices { get; set; } 

    [DataMember] 
    public int I2C_SlaveAdress { get; set; } 

    [DataMember] 
    public string Name { get; set; } 
} 

Pour plus, voir Data Contract Known Types et Known Types.

+0

Merci! J'ai changé le code et ça marche maintenant: Encore une fois, merci! – drummercrm