Портативная библиотека классов: рекомендуемая замена для [Serializable]

Я переношу библиотеку классов .NET Framework С# в портативную библиотеку классов. Одна повторяющаяся проблема заключается в том, как обращаться с классами, украшенными атрибутом [Serializable], так как этот атрибут не является частью подмножества Portable Class Library. Функциональность сериализации в подмножестве Portable Class Library, по-видимому, покрывается DataContractAttribute.

  • Чтобы сохранить как можно большую функциональность в библиотеке портативных классов, достаточно заменить [Serializable] на атрибут [DataContract] (подразумевая, что все поля и свойства, подлежащие сериализации, должны быть украшены [DataMember])?
  • Что (если что-либо) будет ли я не иметь возможность использовать этот подход, который я может выполнять с помощью [Serializable]?
  • Есть ли менее навязчивый подход?

Учитывая, что используются [DataContract] и [DataMember], я рассматриваю возможность изменения кода в следующих строках. Есть ли очевидные недостатки в этом подходе? Есть ли способ сформулировать одно и то же менее подробное?

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

        ...
    }

Ответ 1

Портативные библиотеки классов (PCL) теперь официально устарели [16 августа 2017 года]

Если вы сегодня используете общий код между различными реализациями .NET, вы, вероятно, знаете о портативных библиотеках классов (PCL). С релиз .NET Standard 2.0, теперь официально обесценили PCL и вы должны перенести свои проекты в .NET Standard.

Источник: Объявление .NET Standard 2.0

Портативная библиотека классов (PCL) теперь доступна на всех платформах [14 октября 2013]

До сегодняшнего выпуска было ограничение лицензии с помощью PCL которые означали, что они могут использоваться только в Windows. С сегодняшней версией мы объявляем о выпуске новой автономной версии Справочные сборки PCL с лицензией, которая позволяет ей использоваться на любая платформа, включая не-Microsoft.. Это позволяет разработчикам еще большую гибкость и отличные возможности с .NET.

Источник: Portable Class Library (PCL) теперь доступна на всех платформах

Загрузить: Ссылки на сборку Microsoft.NET Portable Library 4.6 RC

Только для справки разрешенный набор сборок:

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(из Silverlight)

Насколько я знаю, вам нужно пометить поля атрибутом DataMember и добавить атрибут DataContract.

UPDATE

Да.

Вы можете посмотреть, как реализовано Json.NET. Вы можете найти решение в Source\Src\Newtonsoft.Json.Portable при загрузке проекта здесь Json.NET 4.5 Выпуск 10 (источник + двоичный файл).

В основном они используют подход с поставщиком пользовательских атрибутов

//не используйте Serializable

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

//использование настраиваемого поставщика

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

И если проект PORTABLE

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

где Описание OptIn:

 /// <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,

Надеюсь, что это поможет.

ОБНОВЛЕНИЕ 2

Я теряю любые способности, используя [DataContract] вместо [Serializable], или я все еще смогу сделать все, что [Serializable] поддерживает?

Вы можете делать все, что поддерживает Serializable, кроме контролировать, как объект сериализуется вне установки имени и порядка.

Использование DataContractSerializer имеет несколько преимуществ:

сериализуйте что-либо, украшенное [DataMember], даже если оно не доступно для публики

не может сериализовать что-либо, если вы специально не сообщите его ( "opt-in" )

вы можете определить порядок, в котором элементы сериализуются с помощью атрибута [Order=] на [DataMember]

не требует конструктора без параметров для десериализации

на 10% быстрее, чем XmlSerializer.

Подробнее здесь: XmlSerializer vs DataContractSerializer

Также для справки:

DataContract поддерживает сериализацию следующих типов типов в режиме по умолчанию: CLR встроенные типы

Байт-массив, DateTime, TimeSpan, GUID, Uri, XmlQualifiedName, XmlElement и массив XmlNode

Перечисления

Типы, отмеченные атрибутом DataContract или CollectionDataContract

Типы, реализующие IXmlSerializable

Классы массивов и коллекций, включая список, словарь и Hashtable

Типы, отмеченные атрибутом Serializable, включая те, которые реализовать ISerializable

Типы с ни одним из вышеуказанных атрибутов (POCO), но с по умолчанию Конструктор

Ответ 2

Одна вещь, которую вы могли бы сделать, чтобы устранить беспорядок, который вызывает постоянные директивы препроцессора, заключается в том, чтобы отбросить это в один новый класс SerializableAttribute и в основном обмануть компилятор.

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

Затем просто продолжайте украшать ваши классы с помощью Serializable как обычно...

Ответ 3

Для .Net 4.6 и выше DataContract больше не доступен для PCL. Вам нужно добавить пакет Nuget System.Runtime.Serialization.Primitives, доступный здесь: https://www.nuget.org/packages/System.Runtime.Serialization.Primitives/

Примечание для фактической сериализации вам также понадобится реализация, такая как System.Runtime.Serialization.Json, System.Runtime.Serialization.Xml или Newtonsoft.Json.