C#-Protobuff.net无法序列化接口
作者:互联网
我遇到了错误
The type cannot be changed once a serializer has been generated
尝试使用Protobuff.net进行序列化时.我设法减少了查找罪魁祸首的代码,但想知道为什么它无法序列化此属性.
我找到了可以使用的有效解决方案,但对为什么此代码失败的解释感兴趣.
不会序列化:
[ProtoContract]
public class SomeController
{
[ProtoMember(3)]
public int ControllerValue { get; set; }
[ProtoMember(4, AsReference = true)]
private ITest ITestObj { get; set; }
private SomeController(){}
public SomeController(object something, int value)
{
ControllerValue = value;
ITestObj = something as ITest;
}
}
将序列化:
该错误是由SomeController.ITestObj引起的.如果我将此类更改为:
[ProtoContract]
public class SomeController
{
[ProtoMember(3)]
public int ControllerValue { get; set; }
[ProtoMember(4, AsReference = true)]
private TestObj OriginalObject { get; set; }
private ITest ITestObj => OriginalObject as ITest;
private SomeController(){}
public SomeController(TestObj something, int value)
{
ControllerValue = value;
OriginalObject = something;
}
}
工作正常.
工作代码:
下面是一个自包含的HTTP处理程序,它将运行此代码并重现错误:
using System.IO;
using System.Web;
using ProtoBuf;
namespace Handlers
{
/// <summary>
/// Summary description for Test
/// </summary>
public class Test : IHttpHandler
{
[ProtoContract]
public class TestObj : ITest
{
[ProtoMember(1, AsReference = true)]
public SomeController SomeController { get; set; }
[ProtoMember(2)]
public int SomeValue { get; set; }
private TestObj(){}
public TestObj(int something)
{
SomeController = new SomeController(this, something + 1);
SomeValue = something;
}
}
[ProtoContract]
public class SomeController
{
[ProtoMember(3)]
public int ControllerValue { get; set; }
[ProtoMember(4, AsReference = true)]
private ITest ITestObj { get; set; }
private SomeController() { }
public SomeController(object something, int value)
{
ControllerValue = value;
ITestObj = something as ITest;
}
}
[ProtoContract]
[ProtoInclude(5, typeof(TestObj))]
public interface ITest
{
[ProtoMember(6, AsReference = true)]
SomeController SomeController { get; set; }
[ProtoMember(7)]
int SomeValue { get; set; }
}
public void ProcessRequest(HttpContext context)
{
var testObj = new TestObj(5);
var serialised = Serialiser.Serialise(testObj);
var deserialised = Serialiser.Deserialise<TestObj>(serialised);
HttpContext.Current.Response.Write(deserialised.SomeValue + "|" + deserialised.SomeController.ControllerValue + "<br>");
}
protected internal class Serialiser
{
protected internal static byte[] Serialise<T>(T objectToSerialise)
{
using (var stream = new MemoryStream())
{
Serializer.Serialize(stream, objectToSerialise);
return stream.ToArray();
}
}
protected internal static T Deserialise<T>(byte[] bytes)
{
using (var stream = new MemoryStream(bytes))
{
return Serializer.Deserialize<T>(stream);
}
}
}
public bool IsReusable
{
get
{
return false;
}
}
}
}
解决方法:
接口…很尴尬.好消息是您可以在代码中给它一个额外的提示(在开始序列化之前):
Serializer.PrepareSerializer<ITest>();
如果代码可以提前更好地检测到这一点,那就太好了,但是:现在,上面的内容应该会有所帮助.因此,作为示例,我将以下代码放入静态类型初始化程序中:
static Handler1()
{
Serializer.PrepareSerializer<ITest>();
}
但是它也可以进入global.asax或开始序列化之前发生的任何其他情况.
标签:serialization,protocol-buffers,protobuf-net,c 来源: https://codeday.me/bug/20191026/1937059.html