我正在尝试发出以下内容:
这是一个struct,它将作为属性包含在动态发生的类中:
public struct GeoPoint
{
public double? lat { get; set; }
public double? lon { get; set; }
}
我必须发出以下课程:
public class GeoPointOwner
{
public GeoPoint GeoPoint{get; set;}
public double? Getlat ()
{
return GeoPoint.lat;
}
}
我无法弄清楚如何正确发射方法GeoPointOwner.Getlat
这是我的代码:
var mbGet = typeBuilder.DefineMethod("Getlat", MethodAttributes.Public, typeof(double?), Type.EmptyTypes);
var genGet = mbGet.GetILGenerator();
genGet.Emit(OpCodes.Ldarg_0);
//getMethodInfo below is MethodInfo of Getter of GeoPoint property
genGet.Emit(OpCodes.Call, getMethodInfo);
var getMethod = typeof(GeoPoint).GetProperty("lat").GetGetMethod(true);
//code emitted below fails when invoked
genGet.Emit(OpCodes.Callvirt, getMethod);
genGet.Emit(OpCodes.Stloc_0);
genGet.Emit(OpCodes.Ret);
答案 0 :(得分:2)
正如我在评论中建议的那样,如果出现这样的错误,最好在生成的程序集上使用PEVerify。在您的代码上使用它将帮助您解决它。
如果我在生成的程序集上运行它,我会收到此错误:
[GeoPointOwner :: Getlat] [offset 0x00000006]值类型方法的Callvirt。
您无法使用callvirt
来调用值类型的方法(在您的情况下,这是GeoPoint.lat
的获取者),而是使用call
。
修好后,我收到两个新错误:
[GeoPointOwner :: Getlat] [offset 0x00000006] [找到值'ConsoleApplication1.GeoPoint'] [预期值'ConsoleApplication1.GeoPoint'的地址]堆栈上的意外类型。
[GeoPointOwner :: Getlat] [offset 0x0000000B]无法识别的局部变量编号。
我要先修复第二个。您正在使用stloc_0
,它将堆栈顶部的值存储到本地变量#0。它失败了,因为你没有声明任何本地人。我不明白你为什么这样做,因为你不需要任何当地人。您可以直接返回call
的结果,以便删除stloc_0
。
第一个错误更复杂。如果要在值类型上调用方法,实际上需要引用该类型的变量。我们现在没有变量,这意味着我们必须创建一个变量(使用DeclareLocal()
),将值保存到本地(stloc
),然后加载该地址的地址({{ 1}})。有关更多信息,请参阅问题 Method invocation on a struct? 。
通过这些更改,您的代码将变为:
ldloca