与二进制格式化程序的区别
本文关键字:区别 程序 格式化 二进制 | 更新日期: 2023-09-27 18:30:22
我正在尝试更改现有WCF net.tcp项目中的序列化程序,该项目使用客户端和服务器上的共享实体。我很难弄清楚原型网(V2480)这里的图表说我可以序列化私有成员,但找不到文档来做到这一点,没有属性可以吗?如何启用图形模式(作为参考),如此处所述
这会解决 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|调试|ProtobufTEsts.Form1|原始布夫 更改项目数 : 1000
使用二进制Forrmatter
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|调试|ProtobufTEsts.Form1|二进制格式化程序 更改项数 : 0
有没有办法让protobuf表现得像二进制格式化程序,但保留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;
}
啊,我现在明白这个问题了; 这一行是有问题的:
TypeModel compiled = model.Compile();
return compiled;
如果使用 Compile(),它会创建一个正式程序集(在内存中),该程序集必须遵守程序集的常规规则,特别是:成员可访问性。这意味着它无法访问您的私人服务器。
相反,请使用:
model.CompileInPlace();
return model;
这将执行部分编译,但继续使用 DynamicMethod。这个厚颜无耻的小动物可以选择欺骗它的方式绕过可访问性规则(就像反射一样),所以它可以继续使用私有二传手。
请注意,该模型也是根据需要就地编译(在更精细的级别)的,因此对 CompileInPlace 的调用并不是绝对必要的,但有助于提前完成所有操作。
为了完整起见,还有一个额外的 Compile(字符串,字符串)重载,可用于在磁盘上生成单独的序列化 dll,可以在运行时引用和使用,而无需任何元编程。
是的,protobuf-net 可以序列化私有字段,并且没有属性。我不在电脑上,所以这可能需要调整:
var metaType = RuntimeTypeModel.Default.Add(typeof(SomeClass), false);
// for each field in a known order
metaType.Add(fieldName, someUniqueTag);
在属性驱动的用法中,还有 ImplicitFields.AllFields,它会自动根据您想要的用法配置它,但我还没有向 MetaType 添加 ImplicitFields 帮助程序方法。我会把它添加到我的列表中!
注意:标记(=字段)编号对于protobuf很重要,并且在反序列化时必须能够重现相同的数字映射。
您可能需要考虑的另一个选项是(反)序列化回调,它允许您知道它当前正在序列化/反序列化(通过之前/之后的方法调用)。这可能是在一段时间内禁用副作用(如反序列化)的另一种方法。