2017-03-26 7 views
3

Après l'apprentissage ne sérialisation des propriétés privées dans une classe, je commencé à utiliser DataContract et DataMember annotations.C# - sérialisation propriété privée comme attribut (données contrat)

J'ai une propriété de chaîne privée dans ma classe que je voudrais sérialiser en tant qu'attribut et non en tant qu'élément.

[DataContract] 
public class Channel 
{ 
    private string m_Name = string.Empty; 
    private DateTime? m_TxTime = null; 

    [DataMember, XmlAttribute("name")] 
    public string Name 
    { 
     get 
     { 
      return m_Name; 
     } 
     set 
     { 
      m_Name = value; 
     } 
    } 

    public DateTime? TxTime 
    { 
     get 
     { 
      return m_TxTime; 
     } 
     set 
     { 
      m_TxTime = value; 
     } 
    } 

    [DataMember, XmlAttribute("txTime")] 
    private string txTimeForSerialization 
    { 
     get 
     { 
      if (TxTime.HasValue) 
      { 
       return TxTime.Value.ToString("o"); 
      } 
      else 
      { 
       return null; 
      } 
     } 
    } 
} 

Essayer d'utiliser la DataMember et XmlAttribute annotations ensemble m'a donné cette sortie:

<channel name="NAME"> 
    <TxTime>2017-03-26T13:15:56.8042989+03:00</TxTime> 
</channel> 

Le résultat que je veux est ce -

<channel name="NAME" txTime="2017-03-26T13:15:56.8042989+03:00" /> 

La façon dont je sérialisé est en utilisant le XmlSerializer -

using (FileStream fs = new FileStream("channels.txt", FileMode.Create)) 
{ 
    XmlSerializer serializer = new XmlSerializer(typeof(Channel)); 
    serializer.Serialize(fs, objectName); 
} 
+0

'XmlSerializer' ne sérialise que les champs et propriétés publics. En outre, si vous souhaitez l'utiliser, vous n'avez pas besoin des attributs DataContract et DataMember car ils sont utilisés par DataContractSerializer. –

+0

'DataContractSerializer' n'utilise pas d'attributs XML. Voir [Comment contrôler la sérialisation .NET DataContract de manière à utiliser les attributs XML au lieu des éléments?] (Http://stackoverflow.com/q/591907/3744182). L'implémentation de 'IXmlSerializable' comme indiqué ci-dessous devrait fonctionner pour les deux sérialiseurs. – dbc

Répondre

0

Créer « wrapper » pour votre classe qui sera responsable du format des désérialisation correct (une sorte de modèle de façade)

[DataContract] 
public class ChannelData 
{ 
    [DataMember, XmlAttribute("name")] 
    public string Name { get; set; } 

    [DataMember, XmlAttribute("txTime")] 
    public string txTimeForSerialization { get; set; } 
} 

Vous pouvez mettre la logique de créer instance de sérialisation dans Channel classe, alors la responsabilité sera sérialisation la logique restera dans la classe Channel - qui conserve l'encapsulation.

public class Channel 
{ 
    public string Name { get; set; } 
    public DateTime? TxTime { get; set; } 

    public Channel() 
    { 
     Name = string.Empty; 
     TxtTime = null; 
    } 

    public ChannelData ToSerialization() 
    { 
     var data = new ChannelData(); 
     data.Name = Name; 
     data.txTimeForSerialization = TxTime.HasValue ? TxTime.Value.ToString("o") : null; 
    } 
} 

Avec emballage, vous n'avez pas besoin « réfléchir à différentes solutions de contournement » pour les formats différents, vos classes « couche d'affaires » reste « clair » et wrappers manipuleront le formatage.

0

Si vous voulez coller avec votre classe Channel actuelle, vous devez implémenter l'interface IXmlSerializer et sa méthode WriteXml. C'est la seule façon de sérialiser les propriétés privées via XmlSerializer.

public class Channel : IXmlSerializable 
{ 
    private string m_Name = string.Empty; 
    private DateTime? m_TxTime = null; 

    public string Name 
    { 
     get 
     { 
      return m_Name; 
     } 
     set 
     { 
      m_Name = value; 
     } 
    } 

    public DateTime? TxTime 
    { 
     get 
     { 
      return m_TxTime; 
     } 
     set 
     { 
      m_TxTime = value; 
     } 
    } 

    private string txtTimeForSerialization 
    { 
     get 
     { 
      if (TxTime.HasValue) 
      { 
       return TxTime.Value.ToString("o"); 
      } 
      else 
      { 
       return null; 
      } 
     } 
    } 

    public XmlSchema GetSchema() 
    { 
     return null; 
    } 

    public void ReadXml(XmlReader reader) 
    { 
     //implement reader if needed... 
    } 

    public void WriteXml(XmlWriter writer) 
    { 
     writer.WriteAttributeString("name", this.Name); 
     writer.WriteAttributeString("txtTime", this.txtTimeForSerialization); 
    } 
} 

En mettant en œuvre IXmlSerializable vous n'avez pas besoin d'utiliser des attributs plus et votre code pour l'écriture dans channels.txt restent les mêmes:

using (FileStream fs = new FileStream("channels.txt", FileMode.Create)) 
{ 
    XmlSerializer serializer = new XmlSerializer(typeof(Channel)); 
    serializer.Serialize(fs, objectName); 
} 

est ici la sortie:

<?xml version="1.0"?> 
<Channel name="NAME" txtTime="2017-03-26T12:57:25.6780078Z" />