2016-08-02 405 views
2

我们系统中的所有对象都继承了一个基类,该基类有一个object类型的属性。Protobuf-net序列化父类继承对象属性,标记为[ProtoIgnore()]抛出“No serializer defined for type:System.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; } 
    } 
} 

回答

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

这是你所需要的。

+0

感谢您的回应!我不知道你可以做protobufModel.GetSchema(typeof(Vehicle))来调试哪些属性被序列化。您提供的更改工作正常。 – tp182