使用 protobuf-net 反序列化具有某些字段的派生类型的对象

Posted

技术标签:

【中文标题】使用 protobuf-net 反序列化具有某些字段的派生类型的对象【英文标题】:Deserializing an object with protobuf-net with derived type for some field 【发布时间】:2021-05-24 11:41:04 【问题描述】:

有一些逻辑使用 protobuf-net 将 DataContainer<BaseClass> 类型的数据存储到某个存储库。假设我需要创建新的 DerivedClass,因此 DataContainer<DerivedClass> 的所有新实例都将被正确序列化,但出于向后兼容的目的,我希望可以选择将以前保存的一些数据反序列化为 DerivedClass,而不更改存储库中的任何数据。

class Program

    
    static void Main(string[] args)
    
        var baseObject = new BaseClass()
        
            Name = "some name"
        ;
        
        using (var stream = new MemoryStream())
        
            ProtoBuf.Serializer.Serialize(stream, new DataContainer<BaseClass> Data = baseObject, DataBase64 = "base class Base64");
            stream.Seek(0, SeekOrigin.Begin);
            //System.InvalidCastException: 'Unable to cast object of type 'BaseClass' to type 'DerivedClass'.'
            var result = ProtoBuf.Serializer.Deserialize<DataContainer<DerivedClass>>(stream);
        
    



public interface IDataInterface




[ProtoBuf.ProtoContract]
[ProtoInclude(1001, typeof(DerivedClass))]
public class BaseClass: IDataInterface

    [ProtoBuf.ProtoMember(1)]
    public string Name  get; set; 


[ProtoBuf.ProtoContract]
public class DerivedClass : BaseClass

    [ProtoBuf.ProtoMember(1)]
    public int Index  get; set; 


public interface IContainerInterface

    IDataInterface Content  get; 


[ProtoContract]
public class DataContainer<T> : IContainerInterface where T: IDataInterface

    [ProtoMember(1)]
    public T Data  get; set; 

    [ProtoMember(2)]
    public string DataBase64  get; set; 
    
    public IDataInterface Content => this.Data;

有没有办法从序列化的DataContainer&lt;BaseClass&gt; 中反序列化DataContainer&lt;DerivedClass&gt;?另一种方法是在反序列化DataContainer&lt;BaseClass&gt; 之后使用一些更高级别的转换器,它只会将其转换为DataContainer&lt;DerivedClass&gt;,但它涉及一些属性应对,我想尽可能避免

【问题讨论】:

将数据模型与序列化类分开可能很有用。这可以在更改数据模型时提供更多的灵活性。 【参考方案1】:

如果您要序列化的项目*是DerivedClass,那么我预计这已经可以工作了。但是,如果您需要反序列化只知道BaseClass 的现有数据,那么您需要反序列化DataContainer&lt;BaseClass&gt;,然后测试以发现Data 实际上是DerivedClass

【讨论】:

感谢您的快速回答。是的,目前所有数据都存储为BaseClass,但随着时间的推移,数据类型将在存储库中混合。我希望编写一些自定义的反序列化器,在某个时候创建​​ DerivedClass 的实例,这是 Serializer.Merge(..) 会做的事情。不完全是,但在某种程度上相似 @Pallaris 这不是继承和泛型通常如何一起工作,虽然...

以上是关于使用 protobuf-net 反序列化具有某些字段的派生类型的对象的主要内容,如果未能解决你的问题,请参考以下文章

使用 protobuf-net 反序列化字典

使用 protobuf-net 反序列化不同的列表

为啥我不能使用 ProtoBuf-Net 正确反序列化我的对象?

使用 ProtoBuf-Net,如何(反)序列化多维数组?

使用 protobuf-net 反序列化 int& 类型

使用知道架构的 protobuf-net 反序列化未知对象