Protobuf-net Serializing Parent Class 继承对象 属性 标记为 [ProtoIgnore()] 抛出 "No serializer defined for type: System.Object"

Protobuf-net Serializing Parent Class inherited object property marked as [ProtoIgnore()] throwing "No serializer defined for type: System.Object"

我们系统中的所有对象都继承了一个基础 class,它有一个 属性 类型的对象。

我也尝试过将 protoignore 属性添加到基础 class 的所有属性中,但这似乎并不奏效。

class Program
{
    static void Main(string[] args)
    {
        Vehicle vehicle = new Vehicle();
        vehicle.BodyStyleDescription = "4x4";
        vehicle.BodyStyleText = "Prestige Medium";

        dynamic protobufModel = TypeModel.Create();
        AddTypeToModel<Vehicle>(protobufModel);

        using (MemoryStream compressed = new MemoryStream())
        {
            using (GZipStream gzip = new GZipStream(compressed, CompressionMode.Compress, true))
            {
                protobufModel.Serialize(gzip, vehicle);
            }
            string str = Convert.ToBase64String(compressed.GetBuffer(), 0, Convert.ToInt32(compressed.Length));
        }
    }

    public static MetaType AddTypeToModel<T>(RuntimeTypeModel typeModel)
    {
        var properties = typeof(T).GetProperties().Select(p => p.Name).OrderBy(name => name);
        return typeModel.Add(typeof(T), true).Add(properties.ToArray());
    }
}

以下是对象的层次结构

 public interface IObjectBaseClass
{
    [ProtoIgnore()]
    object Parent { get; set; }
    [ProtoIgnore()]
    bool IsSaved { get; set; }
    [ProtoIgnore()]
    string XmlAtLoad { get; set; }
}

public class ObjectBaseClass : IObjectBaseClass
{
    public ObjectBaseClass()
    {
    }

    [ProtoIgnore()]
    internal object _Parent;
    [ProtoIgnore()]
    internal bool _IsSaved;
    [ProtoIgnore()]

    internal string _XmlAtLoad;

    [ProtoIgnore()]
    public bool IsSaved
    {
        get { return _IsSaved; }
        set { _IsSaved = value; }
    }

    [ProtoIgnore()]
    public object Parent
    {
        get { return _Parent; }
        set { _Parent = value; }
    }

    [ProtoIgnore()]
    public string XmlAtLoad
    {
        get { return _XmlAtLoad; }
        set { _XmlAtLoad = value; }
    }

}

public class Vehicle : ObjectBaseClass
{
    private string _BodyStyleText;
    private string _BodyStyleDescription;

    public string BodyStyleDescription
    {
        get { return _BodyStyleDescription; }
        set { _BodyStyleDescription = value; }
    }

    public string BodyStyleText
    {
        get { return _BodyStyleText; }
        set { _BodyStyleText = value; }
    }
}

您的问题是,当您执行 typeModel.Add(typeof(T), true).Add(properties.ToArray()) 时,您正在将 T 所有 属性添加到运行时类型模型,包括那些标有 ProtoIgnore。您可以通过调用调试方法 protobufModel.GetSchema(typeof(Vehicle)) which returns:

来查看这一点
message Object {
}
message Vehicle {
   optional string BodyStyleDescription = 1;
   optional string BodyStyleText = 2;
   optional bool IsSaved = 3;
   optional Object Parent = 4;
   optional string XmlAtLoad = 5;
}

要避免添加标有 [ProtoIgnore] 的属性,您可以这样做:

    public static MetaType AddTypeToModel<T>(RuntimeTypeModel typeModel)
    {
        var properties = typeof(T)
            .GetProperties()
            .Where(p => !p.GetCustomAttributes<ProtoIgnoreAttribute>().Any())
            .Select(p => p.Name)
            .OrderBy(name => name);
        return typeModel.Add(typeof(T), true).Add(properties.ToArray());
    }

或者,由于您无论如何都使用 protobuf 属性手动注释某些模型,因此您可以使用 [ProtoContract(ImplicitFields = ImplicitFields.AllPublic)] 标记派生类型,例如:

[ProtoContract(ImplicitFields = ImplicitFields.AllPublic)]
public class Vehicle : ObjectBaseClass
{
    private string _BodyStyleText;
    private string _BodyStyleDescription;

    public string BodyStyleDescription
    {
        get { return _BodyStyleDescription; }
        set { _BodyStyleDescription = value; }
    }

    public string BodyStyleText
    {
        get { return _BodyStyleText; }
        set { _BodyStyleText = value; }
    }
}

使用任一方法,Vehicle 的架构变为:

message Vehicle {
   optional string BodyStyleDescription = 1;
   optional string BodyStyleText = 2;
}

这就是您所需要的。