序列化期间的 TypeLoadException [英] TypeLoadException during serialization

查看:24
本文介绍了序列化期间的 TypeLoadException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我尝试打开我的自定义可视化工具 在 .NET Core 项目(面向 2.2)中的表达式树上,出现以下异常:

When I try to open my custom visualizer on an expression tree in a .NET Core project (targeting 2.2), I get the following exception:

正在调试的进程中的自定义可视化组件抛出了类型为System.TypeLoadException"的未处理异常.

An unhandled exception of type 'System.TypeLoadException' was thrown by the custom visualizer component in the process being debugged.

无法从程序集 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' 加载类型 'System.Runtime.CompilerServices.IsReadOnlyAttribute'.

Could not load type 'System.Runtime.CompilerServices.IsReadOnlyAttribute' from assembly 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.

以下代码(来自问题末尾的堆栈跟踪)似乎存在相同的问题:

The following code (derived from the stack trace, at the end of the question) appears to have the same issue:

// using System;
// using System.IO;
// using System.Runtime.Serialization.Formatters.Binary;
var stream = File.Create(Path.GetTempFileName());
var formatter = new BinaryFormatter();
var data = new VisualizerData(expr); // serialized class with information about a given expression tree
formatter.Serialize(stream, data); // fails with the same exception

当代码在 .NET Core 项目中运行,但使用来自引用的 .NET Framework 程序集(面向 4.7.2)的类 (VisualizerData) 时;该程序集引用了 WPF 程序集.

when the code is running in a .NET Core project, but uses a class (VisualizerData) from a referenced .NET Framework assembly (targeting 4.7.2); that assembly has references to WPF assemblies.

我该如何调试这个问题?可能是什么原因造成的?

请注意,这里没有进行任何反序列化;这就是启动序列化的全部过程.

Note that there isn't any deserialization going on here; this is all while starting up serialization.

VisualizerDataObjectSource.TransferData 的源代码VisualizerDataObjectSource.cs:line 9

堆栈跟踪:

   at System.ModuleHandle.ResolveType(RuntimeModule module, Int32 typeToken, IntPtr* typeInstArgs, Int32 typeInstCount, IntPtr* methodInstArgs, Int32 methodInstCount, ObjectHandleOnStack type)
   at System.ModuleHandle.ResolveTypeHandleInternal(RuntimeModule module, Int32 typeToken, RuntimeTypeHandle[] typeInstantiationContext, RuntimeTypeHandle[] methodInstantiationContext)
   at System.Reflection.RuntimeModule.ResolveType(Int32 metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
   at System.Reflection.CustomAttribute.FilterCustomAttributeRecord(CustomAttributeRecord caRecord, MetadataImport scope, Assembly& lastAptcaOkAssembly, RuntimeModule decoratedModule, MetadataToken decoratedToken, RuntimeType attributeFilterType, Boolean mustBeInheritable, Object[] attributes, IList derivedAttributes, RuntimeType& attributeType, IRuntimeMethodInfo& ctor, Boolean& ctorHasParameters, Boolean& isVarArg)
   at System.Reflection.CustomAttribute.IsCustomAttributeDefined(RuntimeModule decoratedModule, Int32 decoratedMetadataToken, RuntimeType attributeFilterType, Int32 attributeCtorToken, Boolean mustBeInheritable)
   at System.Reflection.CustomAttribute.IsDefined(RuntimeMethodInfo method, RuntimeType caType, Boolean inherit)
   at System.Runtime.Serialization.SerializationEvents.GetMethodsWithAttribute(Type attribute, Type t)
   at System.Runtime.Serialization.SerializationEvents..ctor(Type t)
   at System.Runtime.Serialization.SerializationEventsCache.<>c.<GetSerializationEventsForType>b__1_0(Type type)
   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
   at System.Runtime.Serialization.SerializationEventsCache.GetSerializationEventsForType(Type t)
   at System.Runtime.Serialization.SerializationObjectManager.RegisterObject(Object obj)
   at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, SerializationBinder binder)
   at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Write(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo)
   at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.WriteArrayMember(WriteObjectInfo objectInfo, NameInfo arrayElemTypeNameInfo, Object data)
   at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.WriteArray(WriteObjectInfo objectInfo, NameInfo memberNameInfo, WriteObjectInfo memberObjectInfo)
   at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Write(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo)
   at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, BinaryFormatterWriter serWriter, Boolean fCheck)
   at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Boolean check)
   at ExpressionTreeVisualizer.VisualizerDataObjectSource.TransferData(Object target, Stream incomingData, Stream outgoingData) in C:UsersSpitzsource
eposzspitzExpressionToStringVisualizer.SharedVisualizerDataObjectSource.cs:line 9
   at Microsoft.VisualStudio.DebuggerVisualizers.DebuggeeSide.Impl.ClrCustomVisualizerDebuggeeHost.TransferData(Object visualizedObject, Byte[] uiSideData)

推荐答案

似乎序列化在引用的 .NET Framework 程序集中定义的值类型是问题的根源.

It appears that serializing a value type defined in the referenced .NET Framework assembly is at the root of the problem.

使用以下方法:

static (bool success, string failPath, string errorMessage) CanSerialize(object o, string path = "") {
    var formatter = new BinaryFormatter();
    using (var stream = File.Create(Path.GetTempFileName())) {
        return CanSerialize(o, path, formatter, stream);
    }
}

static (bool success, string failPath, string errorMessage) CanSerialize(object o, string path, BinaryFormatter formatter, Stream stream) {
    if (o == null) { return (false, path, "Null object"); }

    string msg;
    var t = o.GetType();
    if (t.IsPrimitive || t == typeof(string)) { return (true, path, null); }
    try {
        formatter.Serialize(stream, o);
        return (true, path, null);
    } catch (Exception ex) {
        msg = ex.Message;
    }

    List<(string, object)> values;
    if (t.IsArray) {
        values = (o as IEnumerable).ToObjectList()
            .Select((x, index) => ($"[{index}]", x))
            .Where(x => x.Item2 != null)
            .ToList();
    } else {
        values = t.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
            .Where(fld => !fld.IsStatic)
            .Select(fld => ($".{fld.Name}", fld.GetValue(o)))
            .Where(x => x.Item2 != null)
            .ToList();
    }

    foreach (var (name, value) in values) {
        var ret = CanSerialize(value, path + name, formatter, stream);
        if (!ret.success) { return ret; }
    }
    return (false, path, msg);
}

以下struct定义:

[Serializable]
public struct EndNodeData {
    public string Closure { get; set; }
    public string Name { get; set; }
    public string Type { get; set; }
    public string Value { get; set; }
}

以下代码:

var endnodeData = new EndNodeData {
    Closure = null,
    Name = null,
    Type = "int",
    Value = "5"
};
Console.WriteLine(CanSerialize(endnodeData));

打印出来:

(错误,无法从程序集mscorlib,版本=4.0.0.0,文化=中性,PublicKeyToken=b77a5c561934e089"中加载类型System.Runtime.CompilerServices.IsReadOnlyAttribute".)

(False, , Could not load type 'System.Runtime.CompilerServices.IsReadOnlyAttribute' from assembly 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.)

问题似乎出在这种特定类型或一般的值类型上.

It would seem the problem is with this specific type, or value types in general.

这篇关于序列化期间的 TypeLoadException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆