7

我尝试使用以下策略为递归方法生成 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})); )内的递归调用返回null。因为我们实际上是在SaveAssembly()方法内部创建类型,所以这是可以接受的。所以我的问题是:是否可以使用上述构造为递归方法生成 IL?如果不可能,请告诉我用于为递归方法生成 IL 的替代构造。

4

1 回答 1

7

我还没有测试过,但如果我没记错的话,你应该可以简单地使用结果DefineMethod来发出Call指令:

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

ILGenerator ilOfMethod = method.GetILGenerator();

...
ilOfMethod.Emit(OpCodes.Call, method);
于 2011-06-27T07:37:01.857 回答