private static MethodDefinition CreateGetResourceAssemblyStreamOrNullMethod(FieldReference dictionaryField, TypeReference moduleType, MetadataHelper helper)
        {
            // C#:
            // private static Stream GetResourceAssemblyStreamOrNull(AssemblyName assemblyName)
            // {
            //     return EmbeddedResourceNamesByAssemblyName.TryGetValue(assemblyName.Name, out var resourceName)
            //         ? typeof(Module).Assembly.GetManifestResourceStream(resourceName)
            //         : null;
            // }

            var method = helper.DefineMethod(
                "GetResourceAssemblyStreamOrNull",
                MethodAttributes.Private | MethodAttributes.Static | MethodAttributes.HideBySig,
                returnType: "class System.IO.Stream",
                parameterTypes: new[] { "class System.Reflection.AssemblyName" });

            var programBuilder = new ProgramBuilder(method.Body, helper);

            var resourceNameVariable = programBuilder.CreateLocal("string");
            var successLabel         = new Label();

            programBuilder.Append(
                Ldsfld(dictionaryField),
                Ldarg(0),
                Callvirt("instance string System.Reflection.AssemblyName::get_Name()"),
                Ldloca(resourceNameVariable),
                Callvirt("instance bool class System.Collections.Generic.Dictionary`2<string, string>::TryGetValue(!0, !1&)"),
                Brtrue_S(successLabel),

                Ldnull(),
                Ret(),

                successLabel,
                Ldtoken(moduleType),
                Call("class System.Type System.Type::GetTypeFromHandle(valuetype System.RuntimeTypeHandle)"),
                Callvirt("instance class System.Reflection.Assembly System.Type::get_Assembly()"),
                Ldloc(resourceNameVariable),
                Callvirt("instance class System.IO.Stream System.Reflection.Assembly::GetManifestResourceStream(string)"),
                Ret());

            programBuilder.Emit();
            return(method);
        }
        private static MethodDefinition CreateModuleInitializer(
            FieldReference dictionaryField,
            IReadOnlyDictionary <string, string> embeddedResourceNamesByAssemblyName,
            MethodReference assemblyResolveHandler,
            bool isAppDomainHandler,
            MetadataHelper helper)
        {
            // C#:
            // static <Module>()
            // {
            //     EmbeddedResourceNamesByAssemblyName = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
            //     {
            //         ["Some.Assembly.Name"] = @"Some\Embedded\Resource\Path",
            //         ["etc"] = "etc"
            //     };
            //
            //     AppDomain.CurrentDomain.AssemblyResolve += OnAssemblyResolve;
            // }

            var moduleInitializer = helper.DefineMethod(
                ".cctor",
                MethodAttributes.Static | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
                returnType: "void");

            var program = new ProgramBuilder(moduleInitializer.Body, helper);

            // Initialize dictionary field
            program.Append(
                Call("class System.StringComparer System.StringComparer::get_OrdinalIgnoreCase()"),

                Newobj(@"instance void class System.Collections.Generic.Dictionary`2<string, string>::.ctor(
                    class System.Collections.Generic.IEqualityComparer`1<!0>)"));

            foreach (var entry in embeddedResourceNamesByAssemblyName)
            {
                program.Append(
                    Dup(),
                    Ldstr(entry.Key),
                    Ldstr(entry.Value),
                    Callvirt("instance void class System.Collections.Generic.Dictionary`2<string, string>::set_Item(!0, !1)"));
            }

            program.Append(
                Stsfld(dictionaryField));

            if (isAppDomainHandler)
            {
                program.Append(
                    Call("class System.AppDomain System.AppDomain::get_CurrentDomain()"),
                    Ldnull(),
                    Ldftn(assemblyResolveHandler),
                    Newobj("instance void System.ResolveEventHandler::.ctor(object, native int)"),
                    Callvirt("instance void System.AppDomain::add_AssemblyResolve(class System.ResolveEventHandler)"));
            }
            else
            {
                program.Append(
                    Call(@"class [System.Runtime.Loader]System.Runtime.Loader.AssemblyLoadContext
                        class [System.Runtime.Loader]System.Runtime.Loader.AssemblyLoadContext::get_Default()"),

                    Ldnull(),
                    Ldftn(assemblyResolveHandler),

                    Newobj(@"instance void class System.Func`3<
                        class [System.Runtime.Loader]System.Runtime.Loader.AssemblyLoadContext,
                        class System.Reflection.AssemblyName,
                        class System.Reflection.Assembly>::.ctor(object, native int)"),

                    Callvirt(@"instance void class [System.Runtime.Loader]System.Runtime.Loader.AssemblyLoadContext::add_Resolving(
                        class System.Func`3<
                            class [System.Runtime.Loader]System.Runtime.Loader.AssemblyLoadContext,
                            class System.Reflection.AssemblyName,
                            class System.Reflection.Assembly>)"));
            }

            program.Append(
                Ret());

            program.Emit();
            return(moduleInitializer);
        }
        private static MethodDefinition CreateAppDomainAssemblyResolveHandler(MethodReference getResourceAssemblyStreamOrNullMethod, MetadataHelper helper)
        {
            // C#:
            // private static Assembly OnAssemblyResolve(object sender, ResolveEventArgs e)
            // {
            //     using (var stream = GetResourceAssemblyStreamOrNull(new AssemblyName(e.Name)))
            //     {
            //         if (stream is null) return null;
            //
            //         using (var buffer = new MemoryStream(capacity: checked((int)stream.Length)))
            //         {
            //             stream.CopyTo(buffer);
            //             return Assembly.Load(buffer.ToArray());
            //         }
            //     }
            // }

            var method = helper.DefineMethod(
                "OnAssemblyResolve",
                MethodAttributes.Private | MethodAttributes.Static | MethodAttributes.HideBySig,
                returnType: "class System.Reflection.Assembly",
                parameterTypes: new[] { "object", "class System.ResolveEventArgs" });

            var program = new ProgramBuilder(method.Body, helper);

            var streamLocal   = program.CreateLocal("class System.IO.Stream");
            var assemblyLocal = program.CreateLocal("class System.Reflection.Assembly");
            var bufferLocal   = program.CreateLocal("class System.IO.MemoryStream");

            var skipReturningNullLabel = new Label();
            var returnAssemblyLabel    = new Label();
            var skipInnerDispose       = new Label();
            var skipOuterDispose       = new Label();

            program.Append(
                Ldarg(1),
                Callvirt("instance string System.ResolveEventArgs::get_Name()"),
                Newobj("instance void System.Reflection.AssemblyName::.ctor(string)"),
                Call(getResourceAssemblyStreamOrNullMethod),
                Stloc(streamLocal),

                Try(
                    Ldloc(streamLocal),
                    Brtrue_S(skipReturningNullLabel),

                    Ldnull(),
                    Stloc(assemblyLocal),
                    Leave_S(returnAssemblyLabel),

                    skipReturningNullLabel,
                    Ldloc(streamLocal),
                    Callvirt("instance int64 System.IO.Stream::get_Length()"),
                    Conv_Ovf_I4(),
                    Newobj("instance void System.IO.MemoryStream::.ctor(int32)"),
                    Stloc(bufferLocal),

                    Try(
                        Ldloc(streamLocal),
                        Ldloc(bufferLocal),
                        Callvirt("instance void System.IO.Stream::CopyTo(class System.IO.Stream)"),
                        Ldloc(bufferLocal),
                        Callvirt("instance unsigned int8[] System.IO.MemoryStream::ToArray()"),
                        Call("class System.Reflection.Assembly System.Reflection.Assembly::Load(unsigned int8[])"),
                        Stloc(assemblyLocal),
                        Leave_S(returnAssemblyLabel))

                    .Finally(
                        Ldloc(bufferLocal),
                        Brfalse_S(skipInnerDispose),

                        Ldloc(bufferLocal),
                        Callvirt("instance void System.IDisposable::Dispose()"),

                        skipInnerDispose,
                        Endfinally()))

                .Finally(
                    Ldloc(streamLocal),
                    Brfalse_S(skipOuterDispose),

                    Ldloc(streamLocal),
                    Callvirt("instance void System.IDisposable::Dispose()"),

                    skipOuterDispose,
                    Endfinally()),

                returnAssemblyLabel,
                Ldloc(assemblyLocal),
                Ret());

            program.Emit();
            return(method);
        }
        private static MethodDefinition CreateAssemblyLoadContextAssemblyResolveHandler(MethodReference getResourceAssemblyStreamOrNullMethod, MetadataHelper helper)
        {
            // C#:
            // private static Assembly Default_Resolving(AssemblyLoadContext context, AssemblyName name)
            // {
            //     using (var stream = GetResourceAssemblyStreamOrNull(name))
            //     {
            //         if (stream is null) return null;
            //         return context.LoadFromStream(stream);
            //     }
            // }

            var method = helper.DefineMethod(
                "OnAssemblyResolve",
                MethodAttributes.Private | MethodAttributes.Static | MethodAttributes.HideBySig,
                returnType: "class System.Reflection.Assembly",
                parameterTypes: new[] { "object", "class System.ResolveEventArgs" });

            var program = new ProgramBuilder(method.Body, helper);

            var streamLocal   = program.CreateLocal("class System.IO.Stream");
            var assemblyLocal = program.CreateLocal("class System.Reflection.Assembly");

            var skipReturningNullLabel = new Label();
            var returnAssemblyLabel    = new Label();
            var skipDispose            = new Label();

            program.Append(
                Ldarg(1),
                Call(getResourceAssemblyStreamOrNullMethod),
                Stloc(streamLocal),

                Try(
                    Ldloc(streamLocal),
                    Brtrue_S(skipReturningNullLabel),

                    Ldnull(),
                    Stloc(assemblyLocal),
                    Leave_S(returnAssemblyLabel),

                    skipReturningNullLabel,
                    Ldarg(0),
                    Ldloc(streamLocal),
                    Callvirt(@"instance class System.Reflection.Assembly
                        class [System.Runtime.Loader]System.Runtime.Loader.AssemblyLoadContext::LoadFromStream(class System.IO.Stream)"),
                    Stloc(assemblyLocal),
                    Leave_S(returnAssemblyLabel))

                .Finally(
                    Ldloc(streamLocal),
                    Brfalse_S(skipDispose),

                    Ldloc(streamLocal),
                    Callvirt("instance void System.IDisposable::Dispose()"),

                    skipDispose,
                    Endfinally()),

                returnAssemblyLabel,
                Ldloc(assemblyLocal),
                Ret());

            program.Emit();
            return(method);
        }