Protobuf-net序列化父类继承的对象属性,标记为[ProtoIgnore()] thr"没有为类型定义的序列化器:System.Object"

时间:2016-08-02 13:38:55

标签: c# serialization protobuf-net

我们系统中的所有对象都继承了一个具有object类型属性的基类。

我尝试将protoignore属性添加到基类的所有属性中,但这似乎也不起作用。

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; }
    }
}

1 个答案:

答案 0 :(得分:0)

您的问题是当您执行typeModel.Add(typeof(T), true).Add(properties.ToArray())时,您要将T所有属性添加到运行时类型模型中,包括标有ProtoIgnore的模型。您可以通过调用返回的调试方法protobufModel.GetSchema(typeof(Vehicle))来看到这一点:

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;
}

这就是你所需要的。