A non-collectible assembly may not reference a collectible assembly异常

在netcore更新到3.x之后,我们开始打算迁移到这个平台去,但是总会出现一些奇奇怪怪的问题

A non-collectible assembly may not reference a collectible assembly
at System.Reflection.Emit.ModuleBuilder.GetTypeRef(QCallModule module, String strFullName, QCallModule refedModule, String strRefedModuleFileName, Int32 tkResolution)
at System.Reflection.Emit.ModuleBuilder.GetTypeRefNested(Type type, Module refedModule, String strRefedModuleFileName)
at System.Reflection.Emit.ModuleBuilder.GetTypeTokenWorkerNoLock(Type type, Boolean getGenericDefinition)
at System.Reflection.Emit.ModuleBuilder.GetTypeTokenInternal(Type type, Boolean getGenericDefinition)
at System.Reflection.Emit.ILGenerator.Emit(OpCode opcode, Type cls)
at System.Xml.Serialization.CodeGenerator.Castclass(Type target)
at System.Xml.Serialization.CodeGenerator.InternalConvert(Type source, Type target, Boolean isAddress)
at System.Xml.Serialization.SourceInfo.InternalLoad(Type elementType, Boolean asAddress)
at System.Xml.Serialization.XmlSerializationWriterILGen.WriteElement(SourceInfo source, ElementAccessor element, String arrayName, Boolean writeAccessor)
at System.Xml.Serialization.XmlSerializationWriterILGen.WriteElements(SourceInfo source, String enumSource, ElementAccessor[] elements, TextAccessor text, ChoiceIdentifierAccessor choice, String arrayName, Boolean writeAccessors, Boolean isNullable)
at System.Xml.Serialization.XmlSerializationWriterILGen.WriteMember(SourceInfo source, String choiceSource, ElementAccessor[] elements, TextAccessor text, ChoiceIdentifierAccessor choice, TypeDesc memberTypeDesc, Boolean writeAccessors)
at System.Xml.Serialization.XmlSerializationWriterILGen.GenerateTypeElement(XmlTypeMapping xmlTypeMapping)
at System.Xml.Serialization.XmlSerializationWriterILGen.GenerateElement(XmlMapping xmlMapping)
at System.Xml.Serialization.TempAssembly.GenerateRefEmitAssembly(XmlMapping[] xmlMappings, Type[] types, String defaultNamespace)
at System.Xml.Serialization.TempAssembly..ctor(XmlMapping[] xmlMappings, Type[] types, String defaultNamespace, String location)
at System.Xml.Serialization.XmlSerializer.GenerateTempAssembly(XmlMapping xmlMapping, Type type, String defaultNamespace, String location)
at System.Xml.Serialization.XmlSerializer..ctor(Type type, String defaultNamespace)

看问题描述大概是序列化成xml时候出现的问题,我用的System.Xml.Serialization.XmlSerializer类,就随便写了个控制台去debug一下,发现怎么搞都出不了这个异常了。也就是说异常出现还有一些必要条件。

再重审下异常描述,看起来涉及到了反射字样,大概是和动态加载有关系了。

在netcore3.0之后,微软开始支持了可回收程序集 (Collectible Assembly),我们可以创建一个可回收的 AssemblyLoadContext(类似于原来的AppDomain,已过时),用它来加载与卸载程序集。

那么用两个条件一起搜索,就发现GitHub上已经提有这么一个bug:
https://github.com/dotnet/runtime/issues/1388
总结起来就是:
原因:未知,推测是由于XmlSerializer创建的动态的non-Collectible Assembly,与我们输入的类型产生了不良反应,由此导致异常的发生。
作者说等到NET5,在这之后再合并入NET3。

办法:
1、如果继续用AssemblyLoadContext+XmlSerializer的话,需要将AssemblyLoadContext的collectible 属性设置为false。

2、使用Newtonsoft来做序列化,可以回避掉这个问题。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容