Динамическая библиотека содержит только метаданные, без типов - PullRequest
0 голосов
/ 26 октября 2018

Используя .NET 4.7.2, я динамически генерирую .dll во время выполнения, используя

internal class Program
{
    private static void Main(string[] args)
    {
        AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(new AssemblyName("MyAssembly"), AssemblyBuilderAccess.RunAndSave);
        ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("ModuleName");
        TypeBuilder typeBuilder = moduleBuilder.DefineType("MyNamespace.TypeName", TypeAttributes.Public);

        typeBuilder.DefineDefaultConstructor(MethodAttributes.Public);

        // Build the method 'public int ReturnTheAnswer() => 42;'.
        MethodBuilder newMethod = typeBuilder.DefineMethod("ReturnTheAnswer", MethodAttributes.Public, typeof(int), new Type[0]);
        ILGenerator ilGen = newMethod.GetILGenerator();
        ilGen.Emit(OpCodes.Ldc_I4_S, 42);
        ilGen.Emit(OpCodes.Ret);

        Type newType = typeBuilder.CreateType();

        assemblyBuilder.Save("MyAssembly.dll"); // Save the assembly in the programs work directory ('bin\Debug').

        dynamic o = Activator.CreateInstance(newType); // Create an instance of the dynamically created type.
        int r = (int) o.ReturnTheAnswer();

        Debug.Assert(r == 42); // If this doesn't fail, the type has been built correctly, is in fact in the .dll and can be used perfectly fine.
    }
}

, и я могу прекрасно использовать тип в .dll, однако, при просмотре сгенерированного .dll с DotPeek и IL Spy, они оба не показывают никаких пространств имен или типов (хотя они должны показывать тип TypeName в пространстве имен MyNamespace).


Почему сборкакажется пустым при использовании двух разных декомпиляторов, но использование его типов из кода работает отлично?

(приведенный выше пример кода mvce, вы должны быть в состоянии воспроизвести точное поведение, с которым я сталкиваюсь)

1 Ответ

0 голосов
/ 29 октября 2018

Ваш тип не сохраняется, поскольку он объявлен в переходном динамическом модуле .
Метод AssemblyBuilder Save сохраняет только динамические модули без переходных процессов.
См. замечания .

Этот метод сохраняет все не переходные динамические модули, определенные в этом динамическая сборка.
Переходные динамические модули не сохраняются.
Имя файла сборки может совпадать с именем одного из модулей. Если так, то сборка манифест хранится в этом модуле. AssemblyFileName может быть отличается от названий всех модулей, содержащихся в сборка. Если это так, файл сборки содержит только сборку манифест.

Чтобы сохранить тип, вы должны объявить его в непереходном постоянном динамическом модуле , используя одну из перегрузок DefineDynamicModule, которая принимает аргумент fileName, как это:

ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("ModuleName", "MyAssembly.dll");

Ваш полный код будет выглядеть ниже.
Используйте одно и то же имя файла, чтобы объединить ваш тип и манифест в одном файле сборки.

AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(new 
AssemblyName("MyAssembly"), AssemblyBuilderAccess.RunAndSave);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("ModuleName", "MyAssembly.dll");
TypeBuilder typeBuilder = moduleBuilder.DefineType("MyNamespace.TypeName", TypeAttributes.Public);

typeBuilder.DefineDefaultConstructor(MethodAttributes.Public);

// Build the method 'public int ReturnTheAnswer() => 42;'.
MethodBuilder newMethod = typeBuilder.DefineMethod("ReturnTheAnswer", 
MethodAttributes.Public, typeof(int), new Type[0]);
ILGenerator ilGen = newMethod.GetILGenerator();
ilGen.Emit(OpCodes.Ldc_I4_S, 42);
ilGen.Emit(OpCodes.Ret);

Type newType = typeBuilder.CreateType();

assemblyBuilder.Save("MyAssembly.dll"); // Save the assembly in the programs work directory ('bin\Debug').

dynamic o = Activator.CreateInstance(newType); // Create an instance of the dynamically created type.
int r = (int) o.ReturnTheAnswer();

Debug.Assert(r == 42); // If this doesn't fail, the type has been built correctly, is in fact in the .dll and can be used perfectly fine.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...