我收到了错误
生成序列化程序后无法更改类型
尝试使用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;
}
}
}
}
答案 0 :(得分:4)
接口很......很尴尬。好消息是你可以在代码中给它一个额外的提示(在开始序列化之前):
Serializer.PrepareSerializer<ITest>();
如果代码可以提前更好地检测到这一点会很好,但是:现在上面应该会有所帮助。举个例子,我把这个代码放在静态类型初始化器中:
static Handler1()
{
Serializer.PrepareSerializer<ITest>();
}
但它也可以在global.asax或开始序列化之前发生的任何其他地方。