2012-07-27 62 views
3

序列化PropertyInfo應該受支持嗎?如果不是,什麼是最好的解決方法?我知道可以序列化類型(支持它),然後通過屬性查找屬性 - 想象查找可能很昂貴。嘗試序列化PropertyInfo時引發異常

p.s. PropertyInfo用於實現類似於DataLoadOptions.LoadWith http://msdn.microsoft.com/en-us/library/bb548760.aspx的功能。當InvalidOperationException提高

using System.IO; 
using System.Reflection; 
using Microsoft.VisualStudio.TestTools.UnitTesting; 
using ProtoBuf; 

[ProtoContract] 
public class A 
{ 
    [ProtoMember(1)] 
    public PropertyInfo Property { get; set; } 
} 

[TestClass] 
public class UnitTest 
{ 
    [TestMethod] 
    public void TestMethod1() 
    { 
     var value = new A { Property = typeof(string).GetProperty("Length") }; 
     using (var stream = new MemoryStream()) 
     { 
      // Raises InvalidOperationException 
      // "No serializer defined for type: System.Reflection.PropertyInfo" 
      Serializer.Serialize(stream, value); 
     } 
    } 
} 

調用堆棧:

protobuf-net.dll!ProtoBuf.Meta.ValueMember.BuildSerializer() Line 316 C# 
protobuf-net.dll!ProtoBuf.Meta.ValueMember.Serializer.get() Line 188 + 0x24 bytes C# 
protobuf-net.dll!ProtoBuf.Meta.MetaType.BuildSerializer() Line 421 + 0x1f bytes C# 
protobuf-net.dll!ProtoBuf.Meta.MetaType.Serializer.get() Line 344 + 0xe bytes C# 
protobuf-net.dll!ProtoBuf.Meta.RuntimeTypeModel.Serialize(int key, object value, ProtoBuf.ProtoWriter dest) Line 592 + 0x44 bytes C# 
protobuf-net.dll!ProtoBuf.Meta.TypeModel.SerializeCore(ProtoBuf.ProtoWriter writer, object value) Line 178 + 0x14 bytes C# 
protobuf-net.dll!ProtoBuf.Meta.TypeModel.Serialize(System.IO.Stream dest, object value, ProtoBuf.SerializationContext context) Line 209 + 0xe bytes C# 
protobuf-net.dll!ProtoBuf.Meta.TypeModel.Serialize(System.IO.Stream dest, object value) Line 193 + 0x10 bytes C# 
protobuf-net.dll!ProtoBuf.Serializer.Serialize<TestProtoBufNet.A>(System.IO.Stream destination, TestProtoBufNet.A instance) Line 88 + 0x18 bytes C# 
TestProtoBufNet.dll!TestProtoBufNet.UnitTest.TestMethod1() Line 24 + 0x10 bytes C# 

回答

2

要添加噸什麼@ikh已經表示,沒有就是不支持類型。當我參考標準BCL類型時,我在談論常見數據類型,而不是反射類型。 protobuf和protobuf-net的全部要點是以數據爲中心的,但PropertyInfo等是實現,而不是數據。事實上,WinRT對於一個PropertyInfo應該有多少信息有着非常不同的想法。

但是!如果您決定將其序列化,請注意Type支持的IIRC。所以,你可以很可能是通過一個代理做到這一點(沒有經過充分測試,我在iPad在這裏!):

[ProtoContract] 
public class PropertyInfoSurrogate { 
    [ProtoMember(1)] 
    public Type Type { get; set; } 
    [ProtoMember(2)] 
    public string Name { get; set; } 

    public static operator implicit PropertyInfoSurrogate(PropertyInfo value) { 
     if(value == null) return null; 
     return new PropertyInfoSurrogate { 
      Type = value.DeclaringType, Name = value.Name 
     }; 
    } 
    public static operator implicit PropertyInfo(PropertyInfoSurrogate value) { 
     if(value == null) return null; 
     return value.Type.GetProperty(value.Name); 
    } 
} 

然後,你的模型:

model.Add(typeof(PropertyInfo), false) 
    .SetSurrogate(typeof(PropertyInfoSurrogate)); 

重點:經過充分測試,但一些這應該工作。讓我知道你是怎麼辦的。

+0

只需稍微調整一下語法,並使用GetProperty處理不明確的情況,這種方式就像魅力一樣。謝謝馬克。 – user1546077 2012-07-27 19:25:15

+0

@ user1546077沒問題; 「一個小小的語法調整」 - 我得到'運營商'語法顛倒?不幸的是,我總是這麼做。當我記得並想「哦,我總是弄錯了 - 扭轉它們」,事實證明我是正確的*在我扭轉它們之前。嘆。 – 2012-07-27 19:43:28

+0

正確的操作符語法。我編輯了你的原始回覆,所以一旦mods批准,你的原創將看起來很完美。 – user1546077 2012-07-27 19:45:07

1

不幸的是,它看起來像PropertyInfo是不是protobuf網序列化。要序列化其中的數據,您可能必須創建一個單獨的ProtoContract類,該類將存儲PropertyInfo的相關位,然後使用它。

具體來講,通過源代碼protobuf網如何找到串行器用於複雜類型(herehere)讀取,它看起來像的protobuf只能與具有[DataContract]樣屬性的類,具體的工作以下任一:

並且不會與他人合作。

一個簡單的實驗證實了這一點。下面的代碼將運行沒有異常,但如果[DataContract][DataMember]被註釋掉了,然後我得到了同樣的異常,因爲你:

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Linq; 
using System.Runtime.Serialization; 
using System.Text; 

using ProtoBuf; 

namespace ProtobufNetTest2 { 
    [DataContract(Name = "Pet", Namespace = "http://www.example.com")] 
    public class Pet { 
     [DataMember(Name = "Name")] 
     public string Name { get; set; } 
    } 

    [ProtoContract] 
    public class DogMessage { 
     [ProtoMember(1)] 
     public Pet Dog { get; set; } 
    } 

    class Program { 
     static void Main(string[] args) { 
      var dog = new Pet() { 
       Name = "The Dog", 
      }; 

      var dogMessage = new DogMessage() { 
       Dog = dog, 
      }; 

      using (var stream = new MemoryStream()) { 
       Serializer.Serialize(stream, dogMessage); 
      } 
     } 
    } 
} 
+0

作者聲明「支持所有標準BCL類型」,這裏http://code.google.com/p/protobuf-net/wiki/Capabilities。也許PropertyInfo不是標準的BCL類型? – user1546077 2012-07-27 16:03:08

+0

我期望這將是一個標準的BCL類型......但我沒有看到protobuf-net中的任何代碼可以處理這個問題。'PropertyInfo'有一個'[SerializableAttribute]'屬性,但我在protobuf-net中看不到任何處理。可能會更好地等待Marc Gravell出面澄清(他很可能很快會這樣做)。 – ikh 2012-07-27 16:14:53

+0

爲了記錄,protobuf-net支持多種方式來支持沒有屬性的類型;模型可以在運行時指定,某些模型可以自動推斷出來,並且還有更多場景的代理。可用的選項非常微妙。 – 2012-07-27 19:10:40

相關問題