Исключение возникает при попытке сериализовать PropertyInfo
Предполагается ли поддержка сериализации PropertyInfo? Если нет, то каков наилучший обходной путь? Я знаю, что можно сериализовать тип (который поддерживается), а затем искать свойство по его атрибутам - представьте, что поиск может быть дорогим.
P. s. PropertyInfo используется для реализации функциональности, аналогичной DataLoadOptions.LoadWith http://msdn.microsoft.com/en-us/library/bb548760.aspx .
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);
}
}
}
Стек вызовов при вызове InvalidOperationException
:
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 ответа:
Чтобы добавить t, что @ikh уже сказал, Нет, это не поддерживаемый тип. Когда я говорю о стандартных типах BCL, я говорю о типах общих данных, а не о типах отражения. Весь смысл protobuf и protobuf-net заключается в том, чтобы быть ориентированным на данные, но
PropertyInfo
etc-это реализация, а не данные. Действительно, WinRT имеет совершенно другое представление о том, сколько информации должен иметь aPropertyInfo
.Однако! Если вы решили сериализовать его, то обратите внимание, что
Type
is поддерживается 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));
Курсив: полностью непроверенный, но что-товроде , что должно работать. Дай мне знать, как у тебя дела.
К сожалению, похоже, что
PropertyInfo
не сериализуется protobuf-net. Чтобы сериализовать данные в нем, вам, вероятно, придется создать отдельный классProtoContract
, который будет хранить соответствующие битыPropertyInfo
, и использовать его.В частности, читая исходный код для того, как protobuf-net находит сериализатор для сложного типа (здесь и здесь ), похоже, что protobuf может работать только с классами, которые имеют
[DataContract]
-подобные атрибуты, в частности, любой из следующее:
[ProtoContract]
,[DataContract]
,[XmlType]
.И не будет работать с другим.
Простой эксперимент подтверждает это. Следующий код будет выполняться без исключений, но если[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); } } } }