Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#序列化失败-解决方法?_C#_Serialization_Binary_Readonly_Binaryformatter - Fatal编程技术网

C#序列化失败-解决方法?

C#序列化失败-解决方法?,c#,serialization,binary,readonly,binaryformatter,C#,Serialization,Binary,Readonly,Binaryformatter,以下程序导致以下故障: Field in TypedReferences cannot be static or init only 基于此,显而易见的解决方案是: 删除private readonly T\u值上的readonly修饰符 但是,以下两个更改也消除了故障: 将结构数据更改为类数据 将public int[]Content更改为public int Content 有人知道BinaryFormatter的内部发生了什么,允许序列化在第2和第3种情况下继续进行吗 使用系统; 使用

以下程序导致以下故障:

Field in TypedReferences cannot be static or init only
基于此,显而易见的解决方案是:

  • 删除
    private readonly T\u值上的
    readonly
    修饰符
  • 但是,以下两个更改也消除了故障:

  • 将结构数据更改为类数据
  • public int[]Content
    更改为
    public int Content
  • 有人知道BinaryFormatter的内部发生了什么,允许序列化在第2和第3种情况下继续进行吗


    使用系统;
    使用System.IO;
    使用System.Runtime.Serialization;
    使用System.Runtime.Serialization.Formatters.Binary;
    命名空间序列化程序{
    //***助手
    公共静态类序列化程序{
    公共静态内存流序列化到流(TO)
    {
    var stream=newmemoryStream();
    IFormatter formatter=新的BinaryFormatter();
    序列化(流,o);
    回流;
    }
    公共静态T反序列化FromStream(MemoryStream stream)
    {
    IFormatter formatter=新的BinaryFormatter();
    stream.Seek(0,SeekOrigin.Begin);
    返回(T)格式化程序。反序列化(流);
    }
    公共静态T往返(TV){
    返回反序列化FromStream(SerializeToStream(v));
    }
    }
    //***设置数据结构
    [可序列化]
    公共结构包装{
    私有只读T_值;
    公共包装(T值){
    _价值=价值;
    }   
    }
    [可序列化]
    公共结构数据{
    公共内容;
    }
    //***执行测试
    公共课程{
    私有静态void Main(字符串[]args)
    {
    var wrapped=newwrapped(新数据{Content=newint[]{1,2,3});
    var roundtrip=Serializer.roundtrip(已包装);
    控制台写入线(往返);
    }
    }
    }
    
    既然还没有人接,我就试试看

    它可以序列化,但反序列化失败

    我不确定这一点,但我怀疑这是因为作为一个结构,反序列化程序不知道这个数组有多大:

        public int[] Content;
    
    所以它不知道要读取多少字节来填充数组。 作为一个类,它可能会将长度序列化到数据中

    如果将结构和类序列化为不同的文件,它们的内容确实略有不同,序列化类中的一个额外字节是数字3,我猜是数组长度。虽然我还没有研究过二进制输出格式

    “修复”可能与此有关,因此反序列化程序将知道数据流中有多少字节组成了数组。不过,我还没有制定出使用它们的有效解决方案

    编辑:似乎您无法序列化固定大小的缓冲区,因此请忽略上述内容


    所以#2可以工作,因为它将数组长度序列化到数据流中,而#3之所以起作用,是因为在
    int
    中,数组长度是固定字节大小的。

    数组长度被序列化到结构和类的流中,因此这不会成为re:#2当数据是类与结构时,文件中的额外长度只是类与结构的头长度之差。i、 e.这适用于结构02000000002000000005,这适用于类0200000000200000000903000000050300000015。如果更改数组中的元素数,则这两个标头都不会更改。包括数组长度在内的信息是为Content属性编码的,它的序列化字节对于struct vs class不会改变。3元素数组的编码如下:07080200000904000000F040000000000300000B和类似的4元素数组0708020000009040000000000F04000000040000000800000000200000003000000040000000B,其中000F04000000300VS000F040000000400具有长度编码,并且在更改结构vs类时不会更改。完整堆栈跟踪告诉我们代码在此处失败:[ArgumentException:TypedReferences中的字段不能是静态的或仅是init。]System.TypedReference.MakeTypedReference(对象目标,FieldInfo[]flds)以及在该方法中引发它的特定检查是:if(runtimeFieldInfo.IsInitOnly | | runtimeFieldInfo.IsStatic)引发新ArgumentException(Environment.GetResourceString(“Argument_TypedReferenceInvalidField”);因此,我认为类和结构之间的差异与如何通过ObjectManager中的解析加载它们有关。i、 不同的属性可能是为结构而不是为类调用Serialization.ObjectManager.DoValueTypeFixup。DoValueTypeFixup依次调用TypedReference.MakeTypedReference。我不能一步一步地浏览源代码,但如果你加载符号并这样做,它应该变得清晰(呃)。
        public int[] Content;