web-dev-qa-db-fra.com

Bibliothèque de classes portable: remplacement recommandé pour [Sérialisable]

Je porte une bibliothèque de classes .NET Framework C # vers une bibliothèque de classes portable. Un problème récurrent est de savoir comment gérer les classes décorées avec le [Serializable] attribut, car cet attribut ne fait pas partie du sous-ensemble de la bibliothèque de classes portable. La fonctionnalité de sérialisation du sous-ensemble de la bibliothèque de classes portable semble plutôt être couverte par DataContractAttribute .

  • Pour conserver autant de fonctionnalités que possible dans la bibliothèque de classes portable, suffit-il de remplacer [Serializable] avec le [DataContract] attribut (avec l'implication que tous les champs et propriétés soumis à la sérialisation devraient être décorés avec [DataMember] ainsi que)?
  • Que (le cas échéant) vais-je pas pouvoir faire avec cette approche que je peut faire avec [Serializable] appliqué?
  • Existe-t-il une approche moins intrusive?

Étant donné que [DataContract] et [DataMember] sont utilisés, j'envisage de changer le code selon les lignes suivantes. Y a-t-il des défauts évidents avec cette approche? Existe-t-il un moyen de formuler la même chose moins verbeuse?

#if PORTABLE
    [DataContract]
#else
    [Serializable]
#endif
    public class SerializableClass : SerializableBaseClass
    {
       ...
#if !PORTABLE
        protected SerializableClass(SerializationInfo info, StreamingContext context)
             : base(info, context)
        {
        }
#endif
        ...
#if PORTABLE
        [DataMember]
#endif
        private Type1 _serializableField;

#if PORTABLE
        [DataMember]
#endif
        private Type2 SerializableProperty { get; set; }

        ...
    }
43
Anders Gustafsson

Les bibliothèques de classes portables (PCL) sont désormais officiellement obsolètes [16 août 2017]

Si vous partagez du code entre différentes implémentations .NET aujourd'hui, vous connaissez probablement les bibliothèques de classes portables (PCL). Avec la sortie de .NET Standard 2.0, nous déconseillons maintenant officiellement les PCL et vous devez déplacer vos projets vers .NET Standard.

Source: Annonce de la norme .NET 2.

Bibliothèque de classes portable (PCL) désormais disponible sur toutes les plates-formes [14 oct. 2013]

Avant la sortie d'aujourd'hui, il y avait une restriction de licence avec les assemblys de référence PCL, ce qui signifiait qu'ils ne pouvaient être utilisés que sous Windows. Avec la version d'aujourd'hui, nous annonçons une nouvelle version autonome des assemblys de référence PCL avec une licence qui lui permet d'être utilisée sur n'importe quelle plate-forme - y compris celles non Microsoft. Cela permet aux développeurs encore plus de flexibilité et de faire de grandes choses avec .NET.

Source: Bibliothèque de classes portable (PCL) désormais disponible sur toutes les plateformes

Téléchargement: Microsoft .NET Portable Library Reference Assemblies 4.6 RC

Juste à titre de référence, l'ensemble d'assemblages autorisé est:

mscorlib.dll

System.dll

System.Core.dll

System.Xml.dll

System.ComponentModel.Composition.dll (MEF)

System.Net.dll

System.Runtime.Serialization.dll

System.ServiceModel.dll

System.Xml.Serialization.dll

System.Windows.dll (de Silverlight)

Autant que je sache, vous devez marquer les champs avec l'attribut DataMember et ajouter l'attribut DataContract attribut.

[~ # ~] mise à jour [~ # ~]

Oui.

Vous pouvez voir comment Json.NET solution de bibliothèque de classes portable est implémentée. Vous pouvez trouver la solution dans le Source\Src\Newtonsoft.Json.Portable lorsque vous téléchargez le projet à partir d'ici Json.NET 4.5 Release 10 (source + binaire) .

Fondamentalement, ils utilisent une approche avec un fournisseur d'attributs personnalisés

// n'utilise pas Serializable

#if !(SILVERLIGHT || WINDOWS_PHONE || NETFX_CORE || PORTABLE)
  [Serializable]
#endif

// utilise un fournisseur personnalisé

#if NETFX_CORE || PORTABLE
using ICustomAttributeProvider = Newtonsoft.Json.Utilities.CustomAttributeProvider;
#endif 

Et si le projet est [~ # ~] portable [~ # ~]

#if !PocketPC && !NET20
      DataContractAttribute dataContractAttribute = GetDataContractAttribute(objectType);
      if (dataContractAttribute != null)
        return MemberSerialization.OptIn;
#endif

la description OptIn est:

 /// <summary>
    /// Only members must be marked with <see cref="JsonPropertyAttribute"/> or <see cref="DataMemberAttribute"/> are serialized.
    /// This member serialization mode can also be set by marking the class with <see cref="DataContractAttribute"/>.
    /// </summary>
    OptIn,

J'espère que cela aide.

MISE À JOUR 2

Suis-je en train de perdre des capacités en utilisant [DataContract] au lieu de [Serializable], ou serai-je toujours en mesure de faire tout ce que [Serializable] prend en charge?

Vous pouvez faire tout ce que Serializable prend en charge, sauf le contrôle de la façon dont l'objet est sérialisé en dehors de la définition du nom et de la commande.

L'utilisation de DataContractSerializer présente plusieurs avantages:

sérialiser tout ce qui est décoré d'un [DataMember] même s'il n'est pas visible par le public

ne peut rien sérialiser sauf si vous le lui demandez spécifiquement ("opt-in")

vous pouvez définir l'ordre dans lequel les éléments sont sérialisés en utilisant le [Order=] attribut sur le [DataMember]

ne nécessite pas de constructeur sans paramètre pour la désérialisation

est 10% plus rapide que XmlSerializer.

En savoir plus ici: XmlSerializer vs DataContractSerializer

Aussi pour la référence:

DataContract prend en charge la sérialisation des types de types suivants dans le mode par défaut: types intégrés CLR

Tableau d'octets, DateTime, TimeSpan, GUID, Uri, XmlQualifiedName, XmlElement et XmlNode

Enums

Types marqués avec l'attribut DataContract ou CollectionDataContract

Types qui implémentent IXmlSerializable

Tableaux et classes de collection, y compris List, Dictionary et Hashtable

Types marqués avec l'attribut Serializable, y compris ceux qui implémentent ISerializable

Types sans aucun des attributs ci-dessus (POCO) mais avec un constructeur par défaut

43
Matija Grcic

Une chose que vous pourriez faire pour éliminer l'encombrement causé par les directives constantes du préprocesseur est de pousser cela vers une nouvelle classe SerializableAttribute et de tromper le compilateur.

#if PORTABLE
namespace System
{
   public class SerializableAttribute : Attribute
   {
       //this does nothing
   }  
}
#endif

Continuez ensuite à décorer vos classes avec Serializable comme d'habitude ...

10
Steve Danner

Pour .Net 4.6 et versions ultérieures, DataContract n'est plus disponible pour PCL. Vous devez ajouter le package Nuget System.Runtime.Serialization.Primitives disponible ici: https://www.nuget.org/packages/System.Runtime.Serialization.Primitives/

Remarque pour la sérialisation réelle, vous aurez probablement également besoin d'une implémentation telle que System.Runtime.Serialization.Json, System.Runtime.Serialization.Xml ou un Newtonsoft.Json.

2
Lex