编程语言
首页 > 编程语言> > C#-Protobuff.net无法序列化接口

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