Search code examples
c#cildnlib

dnLib-Generated Assembly - TypeLoadException Thrown at Runtime


I am using dnLib to generate MSIL assemblies dynamically from a custom language I'm writing, named CSASM:

string absolute = Path.Combine(Directory.GetCurrentDirectory(), forceOutput ?? $"{asmName}.exe");

ModuleDefUser mod = new ModuleDefUser(asmName, Guid.NewGuid(), new AssemblyRefUser(new AssemblyNameInfo(typeof(int).Assembly.GetName().FullName))){
    Kind = ModuleKind.Console,
    RuntimeVersion = "v4.0.30319"  //Same runtime version as "CSASM.Core.dll"
};
var asm = new AssemblyDefUser($"CSASM_program_{asmName}", new Version(version));
asm.Modules.Add(mod);

// Adding attribute code omitted for brevity

//Adds types to the module and constructs methods and method bodies for those types based on the CSASM source file in question
Construct(mod, source);

mod.Write(absolute);

The generation of the executable is working as intended.

However, when trying to run this executable, the TypeLoadException below is thrown:

System.TypeLoadException: Could not load type 'CSASM.Core.IntPrimitive' from assembly
'CSASM_program_Example, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' due to
value type mismatch.
   at Example.Program.csasm_main()

CSASM_program_Example being the name of assembly for the generated executable, Example.exe.

The type IntPrimitive is actually found in the CSASM.Core.dll assembly, which is also in the same folder as the generated executable.

Due to the extreme lack of documentation surrounding dnLib, I'm essentially stumbling around in the dark here.


In short, is there a reason why the type is trying to be loaded from the wrong assembly?
If so, is there a way that I can remedy this?

Viewing the assembly in dnSpy shows the TypeRefs and MemberRefs referencing correct assemblies, which makes this predicament even more frustrating.


Solution

  • After a very thorough examination of a dnLib DLL, the problem was due to me using Importer.ImportDeclaringType(Type).ToTypeDefOrRef(), which caused value-type TypeSigs to be registered as class-type TypeSigs instead.

    Even though the docs say to use Importer.ImportDeclaringType(Type) over Importer.ImportAsTypeSig(Type) for method and field declarations, you really shouldn't be using it.