2008-11-14 12 views
12

Comment sérialiser un 'Type'?Comment XML sérialiser un 'Type'

Je veux sérialiser en XML un objet qui a une propriété qui est un type d'objet. L'idée est que lorsqu'elle est désérialisée, je peux créer un objet de ce type.

public class NewObject 
{ 
} 

[XmlRoot] 
public class XmlData 
{ 
    private Type t; 

    public Type T 
    { 
     get { return t; } 
     set { t = value; } 
    } 
} 
    static void Main(string[] args) 
    { 
     XmlData data = new XmlData(); 
     data.T = typeof(NewObject); 
     try 
     { 
      XmlSerializer serializer = new XmlSerializer(typeof(XmlData)); 
      try 
      { 
       using (FileStream fs = new FileStream("test.xml", FileMode.Create)) 
       { 
        serializer.Serialize(fs, data); 
       } 
      } 
      catch (Exception ex) 
      { 

      } 
     } 
     catch (Exception ex) 
     { 

     } 
    } 

Je reçois cette exception: « Le type ConsoleApplication1.NewObject n'a pas été prévu Utilisez le XmlInclude ou un attribut SoapInclude pour spécifier les types qui ne sont pas connus statiquement. ».

Où dois-je mettre le [XmlInclude]? Est-ce seulement possible?

Répondre

3

La sérialisation XML sérialise uniquement les champs publics et les valeurs de propriété d'un objet dans un flux XML. La sérialisation XML n'inclut pas les informations de type. Par exemple, si vous avez un objet Book qui existe dans l'espace de noms Library, il n'y a aucune garantie qu'il sera désérialisé dans un objet du même type.

Source: MSDN: Introducing XML Serialization

+0

mais dans la question T est public. –

3

Vous pouvez potentiellement implémenter l'interface IXmlSerializable et utiliser Type.FullName (vous pouvez aussi avoir besoin Type.AssemblyQualifiedName) pour la sérialisation et la Assembly.GetType(string) pour désérialisation de votre élément de type.

3

J'ai fini par convertir le nom du type en une chaîne pour l'enregistrer en XML. Lors de la désérialisation, je charge toutes les DLL et enregistre le nom du type et le type dans un dictionnaire. Lorsque je charge le XML avec le nom du type, je peux rechercher le nom dans la clé du dictionnaire et connaître le type en fonction de la valeur du dictionnaire.

1

Le problème est que le type de XmlData.T est réellement "System.RuntimeType" (une sous-classe de Type), qui n'est malheureusement pas publique. Cela signifie qu'il n'y a aucun moyen de dire à la sérialisation à quels types s'attendre. Je suggère de ne sérialiser que le nom du type, ou un nom complet comme le suggère Jay Bazuzi.

1

laid, mais cela fonctionne. Créez une classe qui inclut le type d'objet et la chaîne sérialisée.

ex

Class dummie 
{ 
    Type objType; 
    string xml; 
} 
17

Type classe ne peut pas être sérialisé parce System.RuntimeType n'est pas accessible à notre code, il est un type CLR interne. Vous pouvez contourner cela en utilisant le nom du type à la place, comme ceci:

public class c 
{  
    [XmlIgnore] 
    private Type t; 
    [XmlIgnore] 
    public Type T { 
     get { return t; } 
     set { 
       t = value; 
       tName = value.AssemblyQualifiedName; 
      } 
    } 

    public string tName{ 
     get { return t.AssemblyQualifiedName; } 
     set { t = Type.GetType(value);} 
    } 
} 
+1

Pour rendre le XML plus joli, vous pouvez ajouter un attribut [XmlElement (ElementName = "T")] 'à la propriété' tName'. – derkyjadex

+1

Deux choses: [XmlIgnore] n'est pas nécessaire sur le champ privé, et le setter T n'a pas besoin de mettre à jour le nom. –

Questions connexes