2012-07-27 34 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

相关问题