Runtime: 问题:从.Net Core 1.0开始的序列化支持

创建于 2016-03-01  ·  38评论  ·  资料来源: dotnet/runtime

大家好,
我听说过.Net Core 1.0中不再支持序列化,因为它不适用于跨平台。 (从记忆中改写)实际上是什么意思? 使用BinaryFormatter的Serialize和Deserialize方法的代码库是否将被完全弃用,并且我必须将代码库转换为protobuf-net吗? 还是我误会了?
谢谢,
-山姆

area-Serialization question

最有用的评论

您是否希望人们真正使用.NET Core,还是像Silverlight那样浪费时间? 如果您希望人们实际使用.NET Core,请使其工作。 如果人们需要序列化,请构建它-无需回话! 这些人实际上是在使用您的产品,他们的意见远比每位Microsoft员工的集体智慧有价值。 您会发现,与Microsoft不同,这些人实际上是在.NET上构建关键任务的东西,如果您希望.NET Core成为任何东西,就必须停止破坏它的用处。 没有人要求您放弃.NET进行完整的重写,您可以随时间推移移植整个.NET框架。 现在您已经完成了。

所有38条评论

@joshfree ,是的,不幸的是,引起混乱的文档。 从那里的建议中,JSON.NET进行json序列化,protobuf-net进行二进制序列化,而datacontractserializer进行xml序列化。 问题是,如果我要执行二进制序列化。 虽然protobuf-net是一个很棒的库,但它是有限的。 在Protobuf-nets存储库中,支持的类型为:
自定义类:
被标记为数据合同
有一个无参数的构造函数
对于Silverlight:公开
许多常见的原语等
一维数组:T []
清单/清单
字典/ IDictionary
任何实现IEnumerable并具有Add(T)方法的类型
过去,这种情况很好,因为binaryformatter一直存在,但是现在不再是这种情况了? 通过protobuf-net对不支持的类型进行二进制序列化的推荐方法是什么? 自己建造?
对于所有这些技术,我仍然还是个新手,因此我可能会完全忘记某些要点。

同样,它们都无法可靠地序列化异常(并保留所有相关数据),例如在分布式计算中(Azure ...)。

@cdrnet点对于像奥尔良IIRC这样的人来说是一个大

@SamuelCox ,您好,正如移植指南@joshfree指出的那样,我们(序列化团队)没有计划将二进制序列化程序引入.NET Core。 如果没有.NET远程处理和.NET Core中的AppDomain的概念,则二进制序列化器的用途要少得多。 请考虑.NET Core中的其他序列化程序,例如DataContractSerializer(DCS),DataContractJsonSerializer(DCJS)和XmlSerializer,它们在.NET Core中将继续受支持。 当然,您也可以考虑基于.NET Core构建的第三方串行器。 也许我应该问一个问题-您是在寻找具有二进制序列化有效负载的序列化程序(如果是,为什么),还是在寻找可以序列化/反序列化您所关心类型的序列化程序? 我们一直在努力使用DCS,DCJS和XmlSerializer支持大多数.NET类型的序列化。 如果您遇到这些序列化器不适合您的任何特定问题,请随时告诉我们。

@cdrnet@ RichiCoder1 ,感谢您的反馈。 有一个公开的问题dotnet / coreclr#2715,用于讨论异常序列化。 请在此添加您的反馈。 我同意能够在分布式系统中序列化异常非常重要。 当前,如果没有.NET Core上的ISerializable,我们将无法像在完整的.NET框架中那样序列化异常。

@zhenlan ,您好,我也许本来应该提到过,我想要binaryformatter的主要原因是对(反)序列化异常以及包含异常的自定义类。

主要用例是分布式系统,将一些对象序列化为字节数组,以便我可以通过tcp / ip发送它。 我意识到,例如,通过JSON.NET将对象序列化为JSON,将该字符串转换为字节数组,通过tcp / ip发送并在另一端一次反转整个过程,可能更常见。 但是,这不仅比序列化为字节数组并从字节数组反序列化为所需的对象还要多得多的开销。

感谢@SamuelCox的澄清。 我想我现在明白您的担心。 二进制序列化是一个封闭的系统。 我建议您考虑其他基于开放标准的序列化,例如Xml或JSON。 您今天可能不需要它,但是它为您提供了更大的灵活性,以防将来您需要支持不同平台之间或使用不同编程语言/脚本的序列化。 不确定数据将有多大,但是如果确实要考虑有效负载的大小,则可以考虑数据压缩,这是当今许多服务器的内置功能。

我比其他任何事情都更在意性能开销。 与直接从对象到二进制文件再反序列化和反序列化相比,似乎浪费了很多操作。 我认为我很高兴现在就关闭此问题,因为至少已得到澄清。 我仍然认为4.6与核心1.0之间存在差距,但我确实知道为什么。

谈话有点迟了,但这是我的两分钱:

我认为相信BinaryFormatter的实用程序仅限于.NET远程处理和AppDomains是错误的。 (过时的)BinaryFormatter与较新的同类产品之间的区别在于,它具有序列化更多奇特的.NET对象(包括闭包,子类型和循环图)的强大功能。 当前线程中列出的其他串行器都无法执行所有这些操作。 包括Prajna和Mobius(aka SparkCLR)之类的Microsoft项目在内的许多尖端分布式框架都必须依靠BinaryFormatter才能起作用,这并非巧合。 这不是.NET世界所独有的:Spark使用缓慢的Java二进制序列化程序对闭包进行序列化。

还有其他(非二进制格式)序列化程序可以复制BinaryFormatter的功能,包括mbrace框架使用的我们自己的FsPickler库。 但是,就我认为将库移植到CoreCLR上是不切实际的努力,CoreCLR已弃用了许多关键API。

从业务角度来看,很高兴看到CoreCLR成为分布式计算/大数据域中JVM可行的跨平台竞争对手。 没有平台为POCO和闭包(二进制或其他方式)提供可靠的序列化支持的平台,这将无法实现。

您是否希望人们真正使用.NET Core,还是像Silverlight那样浪费时间? 如果您希望人们实际使用.NET Core,请使其工作。 如果人们需要序列化,请构建它-无需回话! 这些人实际上是在使用您的产品,他们的意见远比每位Microsoft员工的集体智慧有价值。 您会发现,与Microsoft不同,这些人实际上是在.NET上构建关键任务的东西,如果您希望.NET Core成为任何东西,就必须停止破坏它的用处。 没有人要求您放弃.NET进行完整的重写,您可以随时间推移移植整个.NET框架。 现在您已经完成了。

首先, CSLA .NET依赖于全保真序列化,因为它基于移动对象的概念。

当Silverlight出现并且没有BinaryFormatter或NetDataContractSerializer时,_and_拥有所有这些讨厌的反射限制,我们最终实现了自己的序列化器,该

在后Silverlight时代,问题仍然存在,因为在UWP,WinRT,.NET Core等中无法可靠地使用BF / NDCS。

因此,我认为有一个论点是存在一个全保真序列化器_should_,但是只有在.NET的所有版本中都存在时,它才真正有用(至少是imo)。

@rockfordlhotka @opinionmachine @eiriktsarpalis很高兴听到更多的人也有同感,尽管我觉得如果对它说些礼貌一点@opinionmachine会更有各有千秋。 由于此问题已经解决,我可以想象corefx团队不再监视它。 我建议您纠正@forki提到的关于dotnet / coreclr#2715的问题

我必须同意放弃序列化(以及应用程序域)是一个可怕的想法。 我真的不认为这个决定是经过深思熟虑的。

但是,真正让我前进的是MS并未发布支持应用程序域等所需的代码,而是将其留给社区来使用。

考虑到coreclr应该是.net的“服务器”版本,因此很多服务器功能都留在了地板上。

恰当的例子:决定将StackTrace / StackFrame排除在corefx之外,因为它被某些开发人员“滥用”,并且很少使用(根据MS)。 我相信他们(在经过一轮的强烈反对之后)对此有所了解,但我的意思是真的吗? 谁会想到这个东西?

就其价值而言,我实际上对.net内核感到非常满意,并认为这对于.net而言是向前迈出了一大步,性能改进非常出色,它仍然具有我所关心的几乎所有功能,并且它是跨平台的。 这确实是我唯一遇到的问题。 在适当的地方删除功能有很多价值,只要看看它的简约方法是多么成功。 并不是说我要说.net应该尽可能地简约,那太荒谬了,我个人不同意简约的设计,但是我要说的是,不应因为删除某些功能而对MS表示不满。

@SamuelCox ,谢谢! :-)

重申一下,由于许多原因,.NET Core中缺少API。 这些差距中的一些差距很容易解决(我们正在修复它们); 有些很难修复。 但是,我们确实希望听到您遇到的问题(例如有关序列化的整个线程集),并且希望找到一种方法来解除阻塞您的情况。

跨单个框架版本的任意对象图的二进制序列化非常困难; 跨不同的框架更加困难。 “硬”并不是说我们很难完成工作,而是意味着它对平台的其他目标(我认为我们都应该分享的目标)具有深远的影响:安全性,性能,可靠性。

Json.NET + TypeNameHandling.All + PreserveReferencesHandling.All + MemberSerialization.Fields几乎可以带您到达那里。 但是没有FormatterServices.GetUninitializedObject,因此需要一个构造函数。

没有FormatterServices.GetUninitializedObject

我认为这是核心问题-基于外部反射的序列化框架可以使您受益匪浅,但是需要使用特定的API才能编写这些框架。 我对CoreCLR团队的建议是重新添加此API。

在某个时候,.NET社区(无论是商业还是其他)都将不得不停止一直依赖于Microsoft的控制。 如果对此有如此巨大的要求,并且已经有相当长的一段时间无法使用,那么为什么没有社区活动来提供替代方案呢? Json.NET是社区的替代品,我们一直在使用它。 哎呀,源代码甚至可以在参考源上获得

它似乎可以在其他平台上运行,并且我确信它可以在.NET上正常运行。按照我的看法,这是创建项目(似乎有需求)并获得在早期用社区替代品填补这一空白

我们很喜欢@thecodejunkie ,但我们仍然需要在运行时公开适当的API才能实现此目的。

仅供参考:这适用于.NET Core: Type appDomainType = Type.GetType("System.AppDomain"); 。 是的,它可以让您做很多事情。

只是说,我们已经将前端服务器的响应速度提高了30%,从最大负载下的12核减少到最大负载下的2核,redis缓存大小从1.7Gb减少到350Mb,总体上将Azure托管减少了20%(位更真的)

您猜对了BinaryFormatter!

正在使用netdatacontractserializer

我来这里是为了寻找.Net 4.6.1与BinaryFormatter相比要慢得多的答案。

据我了解,这些API将返回(序列化)。 尽管这不是理想的选择,并且存在一些脆弱的问题,但至少应允许现有代码继续运行。

为核心框架设计另一个简单的对象序列化器也很有价值,该对象序列化器也很轻巧,但对跨机器和潜在的跨版本问题更具弹性

除脆性外,还存在安全性问题。

@blowdart WRT安全性,您是说像https://blog.scrt.ch/2016/05/12/net-serialiception/这样的东西

是的,就是这样。 正如Java今年发现的那样,任何包含类型的序列化格式都是危险的。 当我们删除二进制序列化时,我感到非常高兴,因为我们删除了整个漏洞。

@migueldeicaza @blowdart @SamuelCox
串行器不仅需要用于发送内容,甚至还需要进行过程。
如果正确完成二进制序列化程序,则在处理过程中存储数千万个对象时,它们的性能将完全优于整个本机对象堆。
看到这个:
https://www.infoq.com/articles/Big-Memory-Part-2

理智的集群编程绝对需要序列化API。
传送对象实例CLR->文本-> CLR非常不方便,这是一个巨大的开销。
取出BinaryFormatter也许不是一个错误,因为它非常慢并且数据报很大,但是
除了NFX.Slim之外,它是市场上唯一的序列化器,它支持完整的CLR序列化语义。
请参阅详细的速度和尺寸表:
http://aumcode.github.io/serbench/

使用[OnSer / Deser]系列进行可序列化对于平台内的隐形传送确实有很多意义。
就像在旧的NET中一样,它不是强制性的。 为什么不保留它。
至少在复杂的收藏集(即字典)中支持它,一点也不难。

让每个人都使用JSON-绝对不是一个好主意,因为它比二进制序列化器(不是BinaryFormatter)要慢得多。
似乎每个人都在构建没有业务逻辑的类似Twitter的应用程序?

@itadapter确实有一个选择,那就是JSON.Net并不是镇上唯一的序列化游戏。 还有MsgPack,Protobuf和Microsoft自己的Bond。 (编辑:您的第二个链接叫出Protobuf)。 杰森不是唯一的选择。 但是,仍然存在一个大问题,即使用有趣的语义(异常)序列化.Net对象。

@ RichiCoder1
当然是。 如下图所示,即JIL是最快的JSON序列化程序,但是基于文本的序列化程序都不能接触二进制序列化程序。 Protobuf速度很快,但无法支持真正的多态性和复杂图形。

我要说的是:

  • 二进制序列化程序始终对业务域对象更有效,尤其是当您拥有大量数值数据时
  • 通常,串行器不是仅在系统之间移动数据时必需的,甚至在大内存方法所示的进程内部也是如此。 这不是一种典型的方法,但具有大量的实际意义(即缓存和内存中的社交图遍历)
  • 老实说,“传送”是类似于MS Remoting的技术。 通常,在正确的情况下进行远程处理(没有极其复杂的情况)在群集系统中非常有用。 我们一直使用这种方法,使用本机对象进行编程更容易-当您可以获取DOMAIN对象并将它们按原样发送到另一种方法时,无论是在机架中的本机还是相邻的机器上

“典型人物”的基准,显示了流行的序列化程序:
http://aumcode.github.io/serbench/Specimens_Typical_Person/web/overview-charts.htm

万一这个线程上的任何人都不知道,则可以在corefx中使用二进制序列化程序(包括ISerializable等)
https://github.com/dotnet/corefx/tree/master/src/System.Runtime.Serialization.Formatters

@zhenlan我承担.NetStandard2.0工作的一部分吗?

@ RichiCoder1是的,正确。

@zhenlan 太棒了!

@zhenlan我似乎在Standard的预览版中找不到可用的Serializable Attribute。 我只是想念它吗?

@justinhelgerson它应该在那里。

您是否按照公告博客文章中的说明安装了2.0 Preview1 SDK?

创建.NET Core项目后,如果您创建了类库,是否可以确保.csproj文件具有<TargetFramework>netstandard2.0</TargetFramework> ,如果您创建了控制台应用程序,则请确保<TargetFramework>netcoreapp2.0</TargetFramework>

顺便说一句,由于此线程上的许多人都对二进制序列化程序感兴趣,因此您可能对dotnet / corefx#19119中的讨论感兴趣,该讨论与缩减.NET Core 2.0的[可序列化]有关。 如果您有任何反馈意见,请告诉我们。

@zhenlan非常感谢您的快速回复。 我已经通过NuGet安装了预览,但是没有手动更新.csproj文件。 做到了! 我将阅读有关缩减的信息,并在可能影响用例的情况下提供输入。

@justinhelgerson ,在预览1中没有进行缩减缩放(我们仍在努力!),但是您应该能够在每日构建或将来的预览中试用它们。

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

noahfalk picture noahfalk  ·  3评论

matty-hall picture matty-hall  ·  3评论

omariom picture omariom  ·  3评论

v0l picture v0l  ·  3评论

jkotas picture jkotas  ·  3评论