gpt4 book ai didi

c# - Protobuff.net 无法反序列化接口(interface)

转载 作者:行者123 更新时间:2023-11-30 15:20:09 24 4
gpt4 key购买 nike

我遇到了错误

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 或发生在 开始序列化之前的任何其他地方。

关于c# - Protobuff.net 无法反序列化接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40658248/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com