Генерация IL для рекурсивных методов - PullRequest
7 голосов
/ 27 июня 2011

Я попытался сгенерировать IL для рекурсивного метода, используя следующую стратегию, Сначала я определил тип, используя следующий фрагмент кода

private void InitializeAssembly(string outputFileName)
        {
            AppDomain appDomain = AppDomain.CurrentDomain;
            AssemblyName assemblyName = new AssemblyName(outputFileName);
            assemblyBuilder = appDomain.DefineDynamicAssembly(assemblyName,
                                                              AssemblyBuilderAccess.Save);
            moduleBuilder = assemblyBuilder.DefineDynamicModule(outputFileName, outputFileName + ".exe");
            typeBuilder = moduleBuilder.DefineType(typeName, TypeAttributes.Public);
            methodBuilder = typeBuilder.DefineMethod("Main",
                                    MethodAttributes.Static | MethodAttributes.Public,
                                    typeof(void),
                                    System.Type.EmptyTypes);
            ilGen = methodBuilder.GetILGenerator();

        }

Затем я начал генерировать IL для рекурсивного метода, как показано ниже.

MethodBuilder method = typeBuilder.DefineMethod(
                   “MethodName”,
                   MethodAttributes.Static | MethodAttributes.Public,
                   NodeTypeToDotNetType(func.RetType),
                   parameters);
                ILGenerator ilOfMethod = method.GetILGenerator();

method.DefineParameter();

Для вызова самого метода внутри тела метода я использовал следующую конструкцию,

ilOfMethod.Emit(OpCodes.Call, typeBuilder.GetMethod("MethodName", new System.Type[] {typeof(arg1),typeof(arg2),etc}));

Окончательно сохраните сгенерированную сборку, используя следующий метод.

private void SaveAssembly(string outputFileName)
        {
            ilGen.Emit(OpCodes.Ret);
            typeBuilder.CreateType();
            moduleBuilder.CreateGlobalFunctions();
            assemblyBuilder.SetEntryPoint(methodBuilder);
            assemblyBuilder.Save(outputFileName + ".exe");
        }

К сожалению, это не работает, так как рекурсивный метод вызова метода внутри метода возвращает значение null. Проблема здесь в том, что рекурсивный вызов внутри метода (т.е. ilOfMethod.Emit(OpCodes.Call, typeBuilder.GetMethod("MethodName", new System.Type[] {typeof(arg1),typeof(arg2),etc})); ) возвращает ноль. Поскольку мы на самом деле создаем тип внутри метода SaveAssembly(), это приемлемо. Поэтому мой вопрос таков: возможно ли сгенерировать IL для рекурсивных методов, используя приведенную выше конструкцию? Если это невозможно, пожалуйста, дайте мне знать, что альтернативные конструкции для генерации IL для рекурсивных методов.

1 Ответ

7 голосов
/ 27 июня 2011

Я не проверял его, но если я правильно помню, вы можете просто использовать результат DefineMethod для выдачи инструкции Call:

MethodBuilder method = typeBuilder.DefineMethod("MethodName", ...);
...

ILGenerator ilOfMethod = method.GetILGenerator();

...
ilOfMethod.Emit(OpCodes.Call, method);
...