可移植类库:推荐替换 [Serializable]

Posted

技术标签:

【中文标题】可移植类库:推荐替换 [Serializable]【英文标题】:Portable class library: recommended replacement for [Serializable] 【发布时间】:2012-10-05 21:04:04 【问题描述】:

我正在将 .NET Framework C# 类库移植到可移植类库。一个反复出现的问题是如何处理用[Serializable] 属性修饰的类,因为该属性不是可移植类库子集的一部分。可移植类库子集中的序列化功能似乎被 DataContractAttribute 覆盖。

为了在可移植类库中保留尽可能多的功能,将[Serializable] 替换为[DataContract] 属性是否足够(这意味着所有要进行序列化的字段和属性都需要用@ 装饰987654325@ 也是)? 我能用我可以做的这种方法做什么(如果有的话)与[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) 现已正式弃用 [2017 年 8 月 16 日]

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

来源: Announcing .NET Standard 2.0

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

在今天发布之前,PCL 存在许可限制 引用程序集,这意味着它们只能在 Windows 上使用。 随着今天的发布,我们宣布了一个新的独立版本 PCL 参考程序集,其许可证允许在 任何平台 - 包括非 Microsoft 平台。 这使开发人员能够 更大的灵活性并使用 .NET 做伟大的事情。

来源: Portable Class Library (PCL) now available on all platforms

下载: Microsoft .NET Portable Library Reference Assemblies 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 有几个好处:

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

除非您明确告诉 ("opt-in")

,否则无法序列化任何内容

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

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

比 XmlSerializer 快 10%。

在此处阅读更多信息:XmlSerializer vs DataContractSerializer

也供参考:

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

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

枚举

用 DataContract 或 CollectionDataContract 属性标记的类型

实现 IXmlSerializable 的类型

数组和集合类,包括列表、字典和 哈希表

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

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

【讨论】:

我主要关心的是;用 [DataContract] 和 [DataMember] 装饰是否足以替代 [Serializable]? 非常感谢您提供的信息更新,我将仔细研究 JSON。我是否会失去使用 [DataContract] 而不是 [Serializable] 的任何能力,还是我仍然能够做 [Serializable] 支持的所有事情?【参考方案2】:

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

#if PORTABLE
namespace System

   public class SerializableAttribute : Attribute
   
       //this does nothing
     

#endif

然后像往常一样继续用Serializable 装饰你的类...

【讨论】:

谢谢!但是,使用此解决方案,序列功能将被忽略,对吧? 这不起作用 - 有一个例外,如“类型 *** 未标记为可序列化。” 使用 Shim NuGet 包解决了第一个问题,但是库存序列化不能很好地与 Azure .NET 后端配合使用(非 clr 类型不会被序列化;只是 null 到达 AMS 端)。所以看起来我在关注 DataContractSerializer 为我工作。 SerializableAttributeSystem 命名空间中很重要【参考方案3】:

对于 .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。

【讨论】:

我不知道你能做到这一点!节省了我很多时间,让我的生活更轻松!谢谢!

以上是关于可移植类库:推荐替换 [Serializable]的主要内容,如果未能解决你的问题,请参考以下文章

StreamReader 和可移植类库

使用可移植类库作为 COM 接口

Prism 模块引用可移植类库

可移植类库是不是适用于 .net 3.5?

为啥我应该在 Xamarin 中使用可移植类库?

vs 2013 可移植类库 windows.props 未找到