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

C# Protobuf Net似乎重用现有对象,而不是创建和分配新对象,c#,deserialization,protobuf-net,C#,Deserialization,Protobuf Net,在下面的代码中,有两种静态状态:初始状态和最后状态。第一次创建测试类时,它的状态为InitialStatus。此状态可以通过单独的调用(ChangeStatus)进行更改 当我创建TestClass的对象并更改其状态,然后对该对象进行原型序列化和反序列化时,它似乎覆盖了InitialStatus中的值。因此,从本质上讲,Protobuf似乎重用了现有对象(如果在反序列化数据时可用)。(但如果对象为null,则不会这样做)。是否有某种方法可以自定义此行为,以便在反序列化之后,重构对象,而不是重用现

在下面的代码中,有两种静态状态:初始状态和最后状态。第一次创建测试类时,它的状态为InitialStatus。此状态可以通过单独的调用(ChangeStatus)进行更改

当我创建TestClass的对象并更改其状态,然后对该对象进行原型序列化和反序列化时,它似乎覆盖了InitialStatus中的值。因此,从本质上讲,Protobuf似乎重用了现有对象(如果在反序列化数据时可用)。(但如果对象为null,则不会这样做)。是否有某种方法可以自定义此行为,以便在反序列化之后,重构对象,而不是重用现有变量

[ProtoContract]
public class Status
{
    private static Status _initialStatus;
    public static Status InitialStatus
    {
        get{
            if (_initialStatus == null)
            {
                _initialStatus = new Status{StatusId=-1};
            }
            return _initialStatus;
        }
    }

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

    [ProtoMember(101)]
    public int StatusId{get; private set;}
}

[ProtoContract]
public class TestClass2
{
    public TestClass2()
    {
        Initialize();
    }

    private void Initialize()
    {
        CurrentStatus = Status.InitialStatus;
    }

    [ProtoMember(101)]
    public Status CurrentStatus{get; 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;
    }
}
[协议]
公共阶级地位
{
私有静态状态_initialStatus;
公共静态状态InitialStatus
{
得到{
如果(_initialStatus==null)
{
_initialStatus=新状态{StatusId=-1};
}
返回初始状态;
}
}
私有静态状态_lastStatus;
公共静态状态
{
得到{
如果(_lastStatus==null)
{
_lastStatus=新状态{StatusId=-2};
}
返回最新状态;
}
}
[原成员(101)]
public int StatusId{get;private set;}
}
[原始合同]
公共类TestClass2
{
公共测试类2()
{
初始化();
}
私有void初始化()
{
CurrentStatus=Status.InitialStatus;
}
[原成员(101)]
公共状态当前状态{get;private set;}
公共无效更改状态(状态newStatus)
{
当前状态=新闻状态;
}
}
void Main()
{
TestClass2 test=新的TestClass2();
测试.变更状态(状态.最后状态);
string serializedTest=ProtoUtils.Serialize(测试);
TestClass2 testDeserialized=ProtoUtils.Deserialize(serializedTest);
Assert(Status.InitialStatus.StatusId==-1,“初始状态已更改”);
Assert(Status.LastStatus.StatusId==-2,“上次状态已更改”);
}
公共静态类协议
{
公共静态字符串序列化(对象o)
{
字符串结果=String.Empty;
使用(MemoryStream stream=new MemoryStream())
{
Serializer.Serialize(流,o);
结果=Convert.tobase64字符串(stream.ToArray());
}
result.Dump();
返回结果;
}
公共静态T反序列化(字符串数据)
{
T结果=默认值(T);
如果(数据!=null)
{
字节[]数据字节=Convert.FromBase64String(数据);
使用(数据流=新内存流(数据字节))
{
结果=序列化程序。反序列化(流);
}
}
返回结果;
}
}
选项:

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

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