首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >与BinaryFormatter的区别

与BinaryFormatter的区别
EN

Stack Overflow用户
提问于 2012-04-07 00:45:27
回答 2查看 723关注 0票数 3

我正在尝试更改现有net.tcp项目中的序列化程序,该项目使用客户端和服务器上的共享实体。我很难弄清楚protobuf-net(V2480)图表here说我可以序列化私有成员,但是找不到文档来做这件事,没有属性是可能的吗?如here所述,如何启用图形模式(作为参考

这会解决protobuf触发我的changed items标志的问题吗?例如,我有一个类

代码语言:javascript
复制
 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项)反序列化它的时候

代码语言:javascript
复制
 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

代码语言:javascript
复制
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的性能?

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

代码语言:javascript
复制
 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;
    }
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-04-07 17:36:41

啊,我现在明白这个问题了;这行是有问题的:

代码语言:javascript
复制
TypeModel compiled = model.Compile();
return compiled;

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

取而代之的是:

代码语言:javascript
复制
model.CompileInPlace();
return model;

这将执行部分编译,但会继续使用DynamicMethod。这个厚颜无耻的小东西可以选择欺骗过去的可访问性规则(就像反射一样),所以它可以继续使用私有setter。

请注意,该模型也是在按需的基础上进行就地编译(在更细粒度的级别上),因此对CompileInPlace的调用并不是严格必要的,但有助于提前完成所有工作。

为了完整性,有一个额外的编译(字符串,字符串)重载,可以用来在磁盘上产生一个单独的序列化dll,可以在运行时引用和使用,而不需要任何元编程。

票数 2
EN

Stack Overflow用户

发布于 2012-04-07 00:58:54

是的,protobuf-net可以序列化私有字段,而且不需要属性。我不在PC上,所以这可能需要调整:

代码语言:javascript
复制
var metaType = RuntimeTypeModel.Default.Add(typeof(SomeClass), false);
// for each field in a known order
metaType.Add(fieldName, someUniqueTag);

在属性驱动的用法中,也有ImplicitFields.AllFields可以根据你想要的用法自动配置它,但我还没有在MetaType中添加ImplicitFields助手方法。我会把它添加到我的列表中!

注意:标签(=field)编号对协议很重要,并且在反序列化时必须能够重现相同的编号映射。

您可能需要考虑的另一个选项是(反)序列化回调,它允许您知道它当前正在序列化/反序列化(通过之前/之后的方法调用)。这可以是禁用某个时间间隔的副作用的另一种方法,例如反序列化。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10046467

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档