Protobuf-Net 似乎重用现有对象而不是创建和分配新对象

Posted

技术标签:

【中文标题】Protobuf-Net 似乎重用现有对象而不是创建和分配新对象【英文标题】:Protobuf-Net seems to reuse existing object instead of creating and assigning a new one 【发布时间】:2014-01-06 17:40:20 【问题描述】:

在以下代码中,有 2 个静态状态:初始状态和上次状态。首次创建 Test 类时,它的创建状态为 InitialStatus。可以通过单独的调用 (ChangeStatus) 更改此状态。

当我创建一个 TestClass 对象并更改其状态,然后对该对象进行原型序列化和反序列化时,它看起来会覆盖 InitialStatus 中的值。因此,本质上,Protobuf 似乎在反序列化数据时重用现有对象,如果它可用的话。 (但如果对象为空,它不会那样做)。有什么方法可以自定义此行为,以便在反序列化后重建对象而不是重用现有变量?

[ProtoContract]
public class Status

    private static Status _initialStatus;
    public static Status InitialStatus
    
        get
            if (_initialStatus == null)
            
                _initialStatus = new StatusStatusId=-1;
            
            return _initialStatus;
        
    

    private static Status _lastStatus;
    public static Status LastStatus
    
        get
            if (_lastStatus == null)
            
                _lastStatus = new StatusStatusId=-2;
            
            return _lastStatus;
        
    

    [ProtoMember(101)]
    public int StatusIdget; private set;


[ProtoContract]
public class TestClass2

    public TestClass2()
    
        Initialize();
    

    private void Initialize()
    
        CurrentStatus = Status.InitialStatus;
    

    [ProtoMember(101)]
    public Status CurrentStatusget; private set;

    public void ChangeStatus(Status newStatus)
    
        CurrentStatus = newStatus;
    



void Main()

    TestClass2 test = new TestClass2();

    test.ChangeStatus(Status.LastStatus);


    string serializedTest = ProtoUtils.Serialize(test);
    TestClass2 testDeserialized = ProtoUtils.Deserialize<TestClass2>(serializedTest);

    Debug.Assert(Status.InitialStatus.StatusId == -1, "Initial Status has changed");
    Debug.Assert(Status.LastStatus.StatusId == -2, "Last Status has changed");



public static class ProtoUtils

    public static string Serialize(Object o)
    
        String result = String.Empty;

        using (MemoryStream stream = new MemoryStream())
        
            Serializer.Serialize(stream, o);

            result = Convert.ToBase64String(stream.ToArray());
        
        result.Dump();
        return result;
    

    public static T Deserialize<T>(string data)
    
        T result = default(T);

        if (data != null)
        
            byte[] dataBytes = Convert.FromBase64String(data);

            using (Stream stream = new MemoryStream(dataBytes))
            
                result = Serializer.Deserialize<T>(stream);
            

        

        return result;
    

【问题讨论】:

您好,您能提供ProtoUtils 的代码,以便我测试一下吗? 【参考方案1】:

选项:

在 ProtoContractAttribute 上指定 SkipConstructor - 这将防止在对象创建期间初始化该字段 使用反序列化前回调(用适当属性修饰的实例方法)并擦除字段 - 这发生在构造之后但读取数据之前

【讨论】:

我应该在我的问题中指定这个,但我不能跳过构造函数。主要是因为在我的实际代码中,构造函数确实做了我不能跳过的额外工作。我希望不使用回调。 @RajRao 我个人仍然会使用跳过的构造函数和回调的组合(准确运行所需的代码) - 但是自定义工厂怎么样?我没有提到的第三个选项是您可以让 protobuf-net 使用静态方法来创建实例,然后可以按照您喜欢的任何方式对其进行初始化

以上是关于Protobuf-Net 似乎重用现有对象而不是创建和分配新对象的主要内容,如果未能解决你的问题,请参考以下文章

我可以重复使用对象实例来避免使用 protobuf-net 进行分配吗?

protobuf-net 是不是适合序列化任意对象/域模型?

Automapper - 如何重用对象而不是创建新对象(此对象在列表中)

将 protobuf-net RuntimeTypeModel 编译为 C#,而不是 DLL

使用成员编号保存文档,而不是使用 protobuf-net 和 MongoDB 的名称

用于继承的 Protobuf-net .proto 文件生成