与BinaryFormatter的差异(Differences with BinaryFormatter)

编程入门 行业动态 更新时间:2024-10-26 12:32:28
与BinaryFormatter的差异(Differences with BinaryFormatter)

我正在尝试更改在客户端和服务器上使用共享实体的现有WCF net.tcp项目中的序列化程序。 我很难搞清楚protobuf-net(V2480) 这里的图表说我可以序列化私人成员,但找不到文档来做到这一点,是否可能没有属性? 如何启用图形模式(As Reference),如此处所述

这会解决protobuf触发我更改的项目标记的问题吗? 例如,我有一个班级

public enum FirstEnum { First = 0, Second, Third } public enum AnotherEnum { AE1 = 0, AE2, AE3 } [Serializable()] public class SomeClass { public int SomeClassId { get; set; } public FirstEnum FEnum { get; set; } public AnotherEnum AEnum { get; set; } string thing; public string Thing { get{return thing;} set { if (string.IsNullOrEmpty(value)) throw new ArgumentNullException("Thing"); thing = value; } } private decimal firstAmount; public decimal FirstAmount { get{return firstAmount;} set { if (value != firstAmount) { firstAmount = value; changedItems.Add("FirstAmount changed"); } } } private decimal secondAmount; public decimal SecondAmount { get { return secondAmount; } set { if (value != secondAmount) { secondAmount = value; changedItems.Add("SecondAmount changed"); } } } public decimal ThirdAmount { get { return SecondAmount - FirstAmount; } } public DateTime? SomeDate { get; set; } private List<string> changedItems = new List<string>(); public List<string> ChangedItems { get { return changedItems; } } public int PrivateSet { get; private set; } public SomeClass() { } public SomeClass(decimal first, decimal second) { FirstAmount = first; SecondAmount = second; } public void ClearChangedItems() { changedItems.Clear(); }

当我用(1000项)反序列化它时

var model = CreateModel(); items = (List<SomeClass>)model.Deserialize(returnStream, null, typeof(List<SomeClass>));

2012-04-06 09:14:28.1222 | DEBUG | ProtobufTEsts.Form1 | ProtoBuf更改的项目数:1000

使用BinaryForrmatter

System.Runtime.Serialization.Formatters.Binary.BinaryFormatter binaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); items = (List<SomeClass>)binaryFormatter.Deserialize(returnStream);

2012-04-06 09:14:28.1662 | DEBUG | ProtobufTEsts.Form1 | BinaryFormatter已更改项目数:0

有没有办法让protobuf像binaryFormatter一样运行但保留protobuf的性能?

如何允许私有序列化,这失败了

public static TypeModel CreateModel() { RuntimeTypeModel model = TypeModel.Create(); ///var metaType = RuntimeTypeModel.Default.Add(typeof(SomeClass), false); model.Add(typeof(SomeClass), false) .Add(1, "SomeClassId") .Add(2, "FEnum") .Add(3, "AEnum") .Add(4, "Thing") .Add(5, "FirstAmount") .Add(6, "SecondAmount") .Add(7, "SomeDate") .Add(8, "PrivateSet"); TypeModel compiled = model.Compile(); return compiled; }

I am trying to change the serializer in an existing WCF net.tcp project that uses shared entities on client & server. I am having a hard time figuring out protobuf-net(V2480) The chart here says I can serialize private members but cannot find documentation to do that, is it possible without attributes? How do I enable graph mode(As Reference) as explained here

Will that solve the issue of protobuf triggering my changed items flag? For example I have a class

public enum FirstEnum { First = 0, Second, Third } public enum AnotherEnum { AE1 = 0, AE2, AE3 } [Serializable()] public class SomeClass { public int SomeClassId { get; set; } public FirstEnum FEnum { get; set; } public AnotherEnum AEnum { get; set; } string thing; public string Thing { get{return thing;} set { if (string.IsNullOrEmpty(value)) throw new ArgumentNullException("Thing"); thing = value; } } private decimal firstAmount; public decimal FirstAmount { get{return firstAmount;} set { if (value != firstAmount) { firstAmount = value; changedItems.Add("FirstAmount changed"); } } } private decimal secondAmount; public decimal SecondAmount { get { return secondAmount; } set { if (value != secondAmount) { secondAmount = value; changedItems.Add("SecondAmount changed"); } } } public decimal ThirdAmount { get { return SecondAmount - FirstAmount; } } public DateTime? SomeDate { get; set; } private List<string> changedItems = new List<string>(); public List<string> ChangedItems { get { return changedItems; } } public int PrivateSet { get; private set; } public SomeClass() { } public SomeClass(decimal first, decimal second) { FirstAmount = first; SecondAmount = second; } public void ClearChangedItems() { changedItems.Clear(); }

When I deserialize it with (1000 items)

var model = CreateModel(); items = (List<SomeClass>)model.Deserialize(returnStream, null, typeof(List<SomeClass>));

2012-04-06 09:14:28.1222|DEBUG|ProtobufTEsts.Form1|ProtoBuf Number of changed items : 1000

With BinaryForrmatter

System.Runtime.Serialization.Formatters.Binary.BinaryFormatter binaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); items = (List<SomeClass>)binaryFormatter.Deserialize(returnStream);

2012-04-06 09:14:28.1662|DEBUG|ProtobufTEsts.Form1|BinaryFormatter Number of changed items : 0

Is there a way to get protobuf to behave like the binaryFormatter but preserve the performance of protobuf?

How to allow for private serialization, this fails

public static TypeModel CreateModel() { RuntimeTypeModel model = TypeModel.Create(); ///var metaType = RuntimeTypeModel.Default.Add(typeof(SomeClass), false); model.Add(typeof(SomeClass), false) .Add(1, "SomeClassId") .Add(2, "FEnum") .Add(3, "AEnum") .Add(4, "Thing") .Add(5, "FirstAmount") .Add(6, "SecondAmount") .Add(7, "SomeDate") .Add(8, "PrivateSet"); TypeModel compiled = model.Compile(); return compiled; }

最满意答案

啊,我现在明白这个问题; 这条线有问题:

TypeModel compiled = model.Compile(); return compiled;

如果使用Compile(),它会创建一个正式的程序集(在内存中),必须遵守通常的程序集规则,特别是:成员可访问性。 这意味着它无法访问您的私人sertter。

相反,使用:

model.CompileInPlace(); return model;

这将执行部分编译,但继续使用DynamicMethod。 这个厚颜无耻的小动物可以选择欺骗它超越可访问性规则(很像反射可以),所以它可以继续使用私有的setter。

请注意,该模型也根据需要进行了就地编译(在更细粒度级别),因此对CompileInPlace的调用并非严格必要 ,但可以提前预先完成所有操作。

为了完整起见,还有一个额外的Compile(字符串,字符串)重载,可用于在磁盘上生成单独的序列化dll,可在运行时无需任何元编程即可引用和使用。

Ah, I understand the issue now; this line is problematic:

TypeModel compiled = model.Compile(); return compiled;

If you use Compile(), it creates a formal assembly (in memory) that has to obey the usual rules of assemblies, and in particular: member accessibility. This means it can't access your private sertter.

Instead, use:

model.CompileInPlace(); return model;

This performs a partial compilation, but continues using DynamicMethod. This cheeky little critter has options to spoof its way past accessibility rules (much like reflection can), so it can continue to use the private setter.

Note that the model is also compiled-in-place (at a more granular level) on as as-needed basis, so this call to CompileInPlace is not strictly necessary, but helps do everything up-front an in advance.

For completeness, there is an additional Compile(string,string) overload that can be used to produce a separate serialization dll on disk, that can be referenced and used without any meta-programming at runtime.

更多推荐

本文发布于:2023-08-07 13:15:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1464195.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:差异   BinaryFormatter   Differences

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!