Description
Description
#58932 did not properly fix the issues with collectible load contexts. When trying to serialize a generic collection containing the type from a collectible load context (e.g. System.Collections.Generic.List``1[Module.Bar]
), the assembly from Type.Assembly
is System.Private.CoreLib, which is not collectible, it therefore creates a hard ref to the type and crashes.
Is there a specific reason that the check is on the type's assembly (https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.Xml/src/System/Xml/Serialization/ContextAwareTables.cs#L35)? It seems that Type
has a property called IsCollectible
, which should be preferred or am I missing something?
I have forked the original sample project and modified it (simply changing it to new XmlSerializer(typeof(List<Bar>))
): https://github.com/cvium/AssemblyLoadContextBug
Reproduction Steps
https://github.com/cvium/AssemblyLoadContextBug
dotnet build Module
dotnet build CrashSample
cd CrashSample
dotnet bin/Debug/net8.0/CrashSample.dll
Expected behavior
It serializes the type correctly.
Actual behavior
It crashes with this stacktrace
Unhandled exception. System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
---> System.NotSupportedException: A non-collectible assembly may not reference a collectible assembly.
at System.Reflection.Emit.RuntimeModuleBuilder.GetTypeRefNested(Type type, Module refedModule)
at System.Reflection.Emit.RuntimeModuleBuilder.GetTypeTokenWorkerNoLock(Type type, Boolean getGenericDefinition)
at System.Reflection.Emit.RuntimeModuleBuilder.GetTypeTokenInternal(Type type, Boolean getGenericDefinition)
at System.Reflection.Emit.SignatureHelper.AddOneArgTypeHelperWorker(Type clsArgument, Boolean lastWasGenericInst)
at System.Reflection.Emit.SignatureHelper.AddOneArgTypeHelperWorker(Type clsArgument, Boolean lastWasGenericInst)
at System.Reflection.Emit.RuntimeILGenerator.DeclareLocal(Type localType, Boolean pinned)
at System.Xml.Serialization.CodeGenerator.DeclareLocal(Type type, String name)
at System.Xml.Serialization.CodeGenerator.DeclareOrGetLocal(Type type, String name)
at System.Xml.Serialization.ReflectionAwareILGen.WriteArrayLocalDecl(String typeName, String variableName, SourceInfo initValue, TypeDesc arrayTypeDesc)
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.TempAssembly.GenerateRefEmitAssembly(XmlMapping[] xmlMappings, Type[] types)
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)
at Module.Foo..ctor()
at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean wrapExceptions)
--- End of inner exception stack trace ---
at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean wrapExceptions)
at CrashSample.Program.ExecuteAssembly() in C:\Users\name\RiderProjects\AssemblyLoadContextBug\CrashSample\Program.cs:line 30
at CrashSample.Program.Main(String[] args) in C:\Users\name\RiderProjects\AssemblyLoadContextBug\CrashSample\Program.cs:line 13
Regression?
No response
Known Workarounds
Possible workarounds:
- Wrap the coreclr collection types in a class that originates from a collectible load context thereby forcing the Type.Assembly ALC to be "correct"
- Use DataContractSerializer
Configuration
Running this on Windows 10 x64 using dotnet 8.0.103.
Other information
No response