为什么IL生成的方法调用会抛出InvalidProgramException?

问题描述 投票:0回答:1

我正在运行时(.Net Core 3.0)生成Web API控制器。我所拥有的是一个通用的基本控制器,我可以从中继承生成的控制器,并且在设置http操作时,我想从基类中调用方法并返回其值。当我调用/ api / Foo / 1时,将引发InvalidProgramException。

我想要实现的目标:

public class FooController : GenericBaseController<Foo, int> {

    [HttpGet]
    public Foo Get(int id){
        return base.DoGet(id);
    }
}

基本控制器的外观:

[Route("api/[controller]")]
[ApiController]
public abstract class GenericBaseController<T, TId> : ControllerBase {

    protected T DoGet(TId id)
    { 
        return default(T);
    }
}

[设置方法的类型构建器代码如下:

MethodBuilder builder = tb.DefineMethod('Get', MethodAttributes.Public | MethodAttributes.NewSlot | MethodAttributes.Final, typeof(Foo), typeof(int));

ConstructorInfo httpCtorInfo = typeof(HttpGet).GetConstructors().First();
CustomAttributeBuilder httpAttrBuilder = new CustomAttributeBuilder(httpCtorInfo, new object[0]);
builder.SetCustomAttribute(httpAttrBuilder);

ILGenerator emitter = builder.GetILGenerator();

emitter.Emit(OpCodes.Nop);

emitter.Emit(OpCodes.Ldarg_0);
emitter.Emit(OpCodes.Ldarg_1);

Type baseCrudController = typeof(GenericBaseController<,>).MakeGenericType(typeof(Foo), typeof(int));
MethodInfo baseTypeMethod = baseCrudController.GetMethod("GetInBase", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly);
emitter.Emit(OpCodes.Call, baseTypeMethod);

emitter.Emit(OpCodes.Stloc_0);
emitter.Emit(OpCodes.Ldloc_0);

emitter.Emit(OpCodes.Ret);

我尝试使用在此处https://www.codeproject.com/Articles/14058/Parsing-the-IL-of-a-Method-Body中找到的ilreader从我的OpCodes所获得的内容进行重建。

0000 : nop 
0001 : ldarg.0 
0002 : ldarg.1 
0003 : call instance FooProject.Controllers.GenericBaseController`1[FooProject.Models.Foo,System.Int32]::DoGet() 
0008 : stloc.0 
0009 : br.s 0011 
0011 : ldloc.0 
0012 : ret

我正在运行时(.Net Core 3.0)生成Web API控制器。我所拥有的是一个通用的基本控制器,我可以从中继承生成的控制器,并且在设置http操作时我想...

c# asp.net-core .net-core reflection.emit
1个回答
0
投票

我不得不花很多时间来编译和运行它。一旦执行此操作,它就可以完美运行,因此我不确定按摩的哪一部分可以解决您遇到的问题。我所做的更改:

© www.soinside.com 2019 - 2024. All rights reserved.