43

我正在将 .NET Framework C# 类库移植到可移植类库。一个反复出现的问题是如何处理用该[Serializable]属性修饰的类,因为该属性不是可移植类库子集的一部分。可移植类库子集中的序列化功能似乎由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; }

        ...
    }
4

3 回答 3

43

便携式类库 (PCL) 现已正式弃用[2017 年 8 月 16 日]

如果您现在在不同的 .NET 实现之间共享代码,您可能知道可移植类库 (PCL)。随着 .NET Standard 2.0 的发布,我们现在正式弃用 PCL,您应该将项目迁移到 .NET Standard。

资料来源: 宣布 .NET Standard 2.0

可移植类库 (PCL) 现在可在所有平台上使用 [2013 年 10 月 14 日]

在今天的发布之前,PCL 参考程序集存在许可限制,这意味着它们只能在 Windows 上使用。在今天发布的版本中,我们宣布了一个新的 PCL 参考程序集独立版本,其许可证允许它在任何平台(包括非 Microsoft 平台)上使用。 这使开发人员能够更加灵活地使用 .NET 完成出色的工作。

资料来源: 可移植类库 (PCL) 现在可在所有平台上使用

下载: Microsoft .NET 便携式库参考程序集 4.6 RC

仅供参考,允许的程序集集是:

mscorlib.dll

系统.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属性。

更新

是的。

您可以查看Json.NET可移植类库解决方案是如何实现的。当您从此处Json.NET 4.5 Release 10 (source + binary)下载项目时,您可以在Source\Src\Newtonsoft.Json.Portable中找到解决方案。

基本上,他们使用的是带有自定义属性提供程序的方法

//不要使用可序列化

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

//使用自定义提供者

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

如果项目是可移植的

#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有几个好处:

序列化任何用 a 装饰的东西,[DataMember]即使它不公开可见

除非您明确告诉它(“选择加入”),否则无法序列化任何内容

[Order=]您可以使用属性上的属性定义元素序列化的顺序[DataMember]

不需要无参数构造函数进行反序列化

比 XmlSerializer 快 10%。

在这里阅读更多:XmlSerializer vs DataContractSerializer

也供参考:

DataContract在默认模式下支持以下类型的序列化: CLR 内置类型

字节数组、日期时间、时间跨度、GUID、Uri、XmlQualifiedName、XmlElement 和 XmlNode 数组

枚举

用 DataContract 或 CollectionDataContract 属性标记的类型

实现 IXmlSerializable 的类型

数组和集合类,包括 List、Dictionary 和 Hashtable

标有 Serializable 属性的类型,包括那些实现 ISerializable 的类型

没有上述属性(POCO)但具有默认构造函数的类型

于 2012-10-15T20:39:05.850 回答
10

为了消除常量预处理器指令导致的混乱,您可以做的一件事是将其推到一个新SerializableAttribute类并基本上欺骗编译器。

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

然后继续Serializable像往常一样装饰你的班级......

于 2012-10-15T20:29:00.717 回答
2

对于 .Net 4.6 及更高版本,PCL 不再可以使用 DataContract。您需要在此处添加 Nuget 包 System.Runtime.Serialization.Primitives:https ://www.nuget.org/packages/System.Runtime.Serialization.Primitives/

请注意,对于实际序列化,您可能还需要诸如 System.Runtime.Serialization.Json、System.Runtime.Serialization.Xml 或 Newtonsoft.Json 之类的实现。

于 2016-05-23T15:52:09.870 回答