2016-08-02 46 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