Protobuf-net:无法创建抽象类的实例

基于此处找到的代码: protobuf和List – 如何序列化/反序列化? 我创建了一个通用的“ProtoDictionary”,其值类型为ProtoObject。

这是我的ProtoDictionary代码:

public class ProtoDictionary : Dictionary { public void Add(TKey key, string value) { base.Add(key, new ProtoObject<(value)); } public void Add(TKey key, List value) { base.Add(key, new ProtoObject<List>(value)); } public void Add(TKey key, List value) { base.Add(key, new ProtoObject<List>(value)); } public void Add(TKey key, Dictionary value) { base.Add(key, new ProtoObject<Dictionary>(value)); } public void Add(TKey key, Dictionary value) { base.Add(key, new ProtoObject<Dictionary>(value)); } public void Add(TKey key, List value) { base.Add(key, new ProtoObject<List>(value)); } public ProtoDictionary() { // Do nothing } // NOTE: For whatever reason, this class will not correctly deserialize without this method, even though // the base class, Dictionary, has the SerializableAttribute. It's protected so only the framework can access it. protected ProtoDictionary(SerializationInfo info, StreamingContext context) : base(info, context) { } } 

对于ProtoObject:

 [ProtoContract] [ProtoInclude(1, typeof(ProtoObject))] [ProtoInclude(2, typeof(ProtoObject))] [ProtoInclude(3, typeof(ProtoObject<List>))] [ProtoInclude(4, typeof(ProtoObject<Dictionary>))] [ProtoInclude(5, typeof(ProtoObject<List>))] [ProtoInclude(6, typeof(ProtoObject<Dictionary>))] [ProtoInclude(7, typeof(ProtoObject))] [ProtoInclude(8, typeof(ProtoObject))] [ProtoInclude(9, typeof(ProtoObject))] [ProtoInclude(10, typeof(ProtoObject))] [ProtoInclude(11, typeof(ProtoObject))] [ProtoInclude(12, typeof(ProtoObject))] [ProtoInclude(13, typeof(ProtoObject<List>))] [Serializable] public abstract class ProtoObject { public static ProtoObject Create(T value) { return new ProtoObject(value); } public object Value { get { return ValueImpl; } set { ValueImpl = value; } } protected abstract object ValueImpl { get; set; } protected ProtoObject() { } } [ProtoContract] [Serializable] public sealed class ProtoObject : ProtoObject { public ProtoObject() { } public ProtoObject(T value) { Value = value; } [ProtoMember(1)] public new T Value { get; set; } protected override object ValueImpl { get { return Value; } set { Value = (T)value; } } public override string ToString() { return Value.ToString(); } } 

问题是,当我尝试使用以下代码从SQL反序列化ProtoDictionary时:

 public T Deserialize(IDataReader reader, string columnName) { MemoryStream stream = new MemoryStream(); byte[] buffer = new byte[256]; long startIndex = 0; long bytesRead = reader.GetBytes(reader.GetOrdinal(columnName), startIndex, buffer, 0, buffer.Length); while(bytesRead == buffer.Length) { stream.Write(buffer, 0, (int)bytesRead); startIndex += bytesRead; bytesRead = reader.GetBytes(reader.GetOrdinal(columnName), startIndex, buffer, 0, buffer.Length); } stream.Write(buffer, 0, (int)bytesRead); stream.Seek(0, SeekOrigin.Begin); return (T)Utilities.Deserialize(stream); } 

我收到错误“InvalidOperationException:无法创建抽象类的实例。”

我的StackTrace如下:

   在ctorWrapper()
    at ProtoBuf.ObjectFactory`1.Create()in c:\ protobuf-net_fixed \ trunk \ protobuf-net \ ObjectFactory.cs:第82行
   在ProtoBuf.Serializer`1.Deserialize [TCreation](T&instance,SerializationContext context)c:\ protobuf-net_fixed \ trunk \ protobuf-net \ SerializerT.cs:line 568
   在ProtoBuf.Property.PropertyMessageString`4.DeserializeImpl(TSource source,SerializationContext context)c:\ protobuf-net_fixed \ trunk \ protobuf-net \ Property \ PropertyMessageString.cs:第53行
    at ProtoBuf.Property.PropertyPairString`3.DeserializeImpl(TSource source,SerializationContext context)在c:\ protobuf-net_fixed \ trunk \ protobuf-net \ Property \ PropertyPairString.cs:第53行
    at ProtoBuf.Property.PropertyList`3.DeserializeImpl(TSource source,SerializationContext context,Boolean canSetValue)in c:\ protobuf-net_fixed \ trunk \ protobuf-net \ Property \ PropertyList.cs:line 64
    at ProtoBuf.Property.PropertyList`3.Deserialize(TSource source,SerializationContext context)在c:\ protobuf-net_fixed \ trunk \ protobuf-net \ Property \ PropertyList.cs:第52行
   在ProtoBuf.Serializer`1.Deserialize [TCreation](T&instance,SerializationContext context)c:\ protobuf-net_fixed \ trunk \ protobuf-net \ SerializerT.cs:line 568
    at ProtoBuf.Serializer`1.DeserializeChecked [TCreation](T&instance,SerializationContext source)在c:\ protobuf-net_fixed \ trunk \ protobuf-net \ SerializerT.cs:第400行
    at ProtoBuf.SerializerSimpleProxy`1.Deserialize(TValue&value,SerializationContext source)在c:\ protobuf-net_fixed \ trunk \ protobuf-net \ SerializerProxy.cs:第100行
    at ProtoBuf.Serializer.Deserialize [T](SerializationContext source)在c:\ protobuf-net_fixed \ trunk \ protobuf-net \ Serializer.cs:第302行
   在ProtoBuf.Serializer.Deserialize [T](流源)c:\ protobuf-net_fixed \ trunk \ protobuf-net \ Serializer.cs:第289行
   在C:\ QA \ trunk \ TestFramework \ Core \ Utilities.cs中的Demand.TestFramework.Core.Utilities.Deserialize [T](MemoryStream流):第312行
   在C:\ QA \ trunk \ TestFramework \ Core \ Reports \ CrawlerReport.cs中的Demand.TestFramework.Core.Reports.CrawlerReport.Deserialize [T](IDataReader reader,String columnName):第145行
   在C:\ QA \ trunk \ TestFramework \ Core \ Reports \ CrawlerReport.cs中的Demand.TestFramework.Core.Reports.CrawlerReport.FormatSuite(Int32 parentSuiteId,Guid runId):第70行
   在C:\ QA \ trunk \ TestFramework \ Core \ Reports \ CrawlerReport.cs中的Demand.TestFramework.Core.Reports.CrawlerReport.Format(Guid runId):第150行
    at ServiceLauncher.Form1.btnStart_Click(Object sender,EventArgs e)在C:\ QA \ trunk \ TestFramework \ ServiceLauncher \ Form1.cs:第24行
   在System.Windows.Forms.Control.OnClick(EventArgs e)
   在System.Windows.Forms.Button.OnClick(EventArgs e)
   在System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
   在System.Windows.Forms.Control.WmMouseUp(Message&m,MouseButtons按钮,Int32单击)
   在System.Windows.Forms.Control.WndProc(Message&m)
   在System.Windows.Forms.ButtonBase.WndProc(Message&m)
   在System.Windows.Forms.Button.WndProc(Message&m)
   在System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message&m)
   在System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message&m)
   在System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd,Int32 msg,IntPtr wparam,IntPtr lparam)
   在System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG&msg)
   在System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID,Int32 reason,Int32 pvLoopData)
   在System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason,ApplicationContext context)
   在System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason,ApplicationContext context)
   在System.Windows.Forms.Application.Run(Form mainForm)
   在C:\ QA \ trunk \ TestFramework \ ServiceLauncher \ Program.cs中的ServiceLauncher.Program.Main():第16行
   在System.AppDomain._nExecuteAssembly(RuntimeAssembly程序集,String [] args)
   在System.AppDomain.ExecuteAssembly(String assemblyFile,Evidence assemblySecurity,String [] args)
   在Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   在System.Threading.ThreadHelper.ThreadStart_Context(对象状态)
   在System.Threading.ExecutionContext.Run(ExecutionContext executionContext,ContextCallback回调,对象状态,布尔ignoreSyncCtx)
   在System.Threading.ExecutionContext.Run(ExecutionContext executionContext,ContextCallback回调,对象状态)
   在System.Threading.ThreadHelper.ThreadStart()

我不确定我做错了什么。 任何帮助将不胜感激。

谢谢,丹

这可能仅仅是“v1”中的限制。 我已将此作为“v2”的测试添加 ,并且它已通过(我必须创建UrlStatusTrafficEntry才能进行编译):

  public enum UrlStatus { A,B } public enum TrafficEntry { A } [ProtoContract] public class SerializableException { } [Test] public void TestBasicRoundTrip() { var item = new ProtoDictionary(); item.Add("abc", "def"); item.Add("ghi", new List {UrlStatus.A, UrlStatus.B}); var clone = Serializer.DeepClone(item); Assert.AreEqual(2, clone.Keys.Count); object o = clone["abc"]; Assert.AreEqual("def", clone["abc"].Value); var list = (IList)clone["ghi"].Value; Assert.AreEqual(2, list.Count); Assert.AreEqual(UrlStatus.A, list[0]); Assert.AreEqual(UrlStatus.B, list[1]); } 

使用“v1”,或许根本就不要把它abstract ? (解决方法,不修复)

也; 不需要SerializationInfo ctor; protobuf-net没有使用它(虽然你可以通过提供这个方法并调用MergeBinaryFormatter 实现 protobuf-net)

你需要分离ProtoObject和ProtoObject 吗? protobuf-net似乎在ObjectFactory中创建了一个T类型的对象(以环形方式),我假设T将是ProtoObject,它是抽象的。

对不起,我没有更多的帮助 – 我现在没有太多时间进一步挖掘。