我尝试使用以下策略为递归方法生成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();
}
Run Code Online (Sandbox Code Playgroud)
接下来,我开始为递归方法生成IL,如下所示.
MethodBuilder method = typeBuilder.DefineMethod(
“MethodName”,
MethodAttributes.Static | MethodAttributes.Public,
NodeTypeToDotNetType(func.RetType),
parameters);
ILGenerator ilOfMethod = method.GetILGenerator();
method.DefineParameter();
Run Code Online (Sandbox Code Playgroud)
为了在方法体内调用方法本身,我使用了以下构造,
ilOfMethod.Emit(OpCodes.Call, typeBuilder.GetMethod("MethodName", new System.Type[] {typeof(arg1),typeof(arg2),etc}));
Run Code Online (Sandbox Code Playgroud)
最后使用以下方法保存生成的组件.
private void SaveAssembly(string outputFileName)
{
ilGen.Emit(OpCodes.Ret);
typeBuilder.CreateType();
moduleBuilder.CreateGlobalFunctions();
assemblyBuilder.SetEntryPoint(methodBuilder);
assemblyBuilder.Save(outputFileName + ".exe");
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,由于递归方法调用构造,在方法内部返回null,因此无效.这里的问题是方法内的递归调用(即ilOfMethod.Emit(OpCodes.Call, typeBuilder.GetMethod("MethodName", new System.Type[] {typeof(arg1),typeof(arg2),etc}));
)返回null.由于我们实际在SaveAssembly()方法内部创建了类型,因此这是可以接受的.所以我的问题是:是否有可能使用上述构造为递归方法生成IL?如果不可能,请让我知道用于为递归方法生成IL的替代构造.
我没有测试它,但如果我没记错的话,你应该能够简单地使用结果DefineMethod发出Call指令:
MethodBuilder method = typeBuilder.DefineMethod("MethodName", ...);
...
ILGenerator ilOfMethod = method.GetILGenerator();
...
ilOfMethod.Emit(OpCodes.Call, method);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
622 次 |
| 最近记录: |