【问题标题】:Portable class library: recommended replacement for [Serializable]可移植类库:推荐替换 [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; }

        ...
    }

【问题讨论】:

    标签: c# serialization datacontract serializable portable-class-library


    【解决方案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。

    【讨论】:

    • 我不知道你能做到这一点!节省了我很多时间,让我的生活更轻松!谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-13
    • 1970-01-01
    • 2013-08-24
    相关资源
    最近更新 更多