gpt4 book ai didi

c# - 将一个对象放在 ILGenerator 中的堆栈顶部

转载 作者:行者123 更新时间:2023-11-30 13:51:07 24 4
gpt4 key购买 nike

我必须将一个对象的实例传递给一个函数,所以显然所有要作为参数的信息都将加载到评估堆栈中这是我正在寻找的代码

someClass SomeObject = new someClass();

il.Emit(OpCodes.LoadObject, SomeObject);
il.Emit(OpCodes.CallVirt, MethodInfo Function);


public void Function(Object obj)
{
Type type = typeof(obj);
//do something w.r.t to the type
}

我不需要任何类型的信息存储在类中,我不能使用任何原始类型来做出决定

最后我读到我可以使用指针来加载使用一些操作码的类型......但我完全迷失在这里,任何帮助或指向正确方向的指针都会很棒:)

[更新]

好吧,我找到了我自己问题的答案,尝试了一下,效果很好不知道这是否是正确的方法,但我可以成功创建对象并将其加载到堆栈中并将其传递给函数

ConstructorInfo ci = typeof(SomeClass).GetConstructor(System.Type.EmptyTypes);
IL.Emit(OpCodes.Newobj, ci);
IL.Emit(OpCodes.Call, SomeFunctionMethodInfo);

SomeFunctionMethodInfo 是一个以 Object 作为参数的函数,我已经成功地将对象传递给函数并且可以操作它并将类作为对象返回。

我在任何地方都找不到对这个例子的引用,只是通过 MSDN 弄明白了,我做错了什么或者有什么缺点吗?请专家指正或提供更好的答案

最佳答案

你不能在 IL 中凭空获取引用,除非你将引用编码为 IntPtr 文字,在这种情况下:
A。不要这样做
b.你需要 pin , 和
C。不要这样做。

最佳方法取决于您正在编写的方法的签名。如果它是静态的并且不带任何参数……好吧,这有点棘手。就我个人而言,我倾向于将一个对象传递给生成的方法,并让委托(delegate)从那里获取它需要的任何外部数据。但另一种方法是生成一个,并将方法编写为访问类型字段的实例方法。

区别(因此我更喜欢)是第一个方法(最多)需要一个 object[] 参数——你可以使用 DynamicMethod;第二个需要 MethodBuilderTypeBuilderModuleBuilderAssemblyBuilder 等,因此工作量更大。

我提到 object[] 的原因是通常您希望生成的方法有一个共同的签名,即使它们需要不同的输入。这使您可以绑定(bind)到固定的委托(delegate)类型并使用更快的 Invoke 执行(DynamicInvoke 很慢)。

例如:

class SomeType { }
delegate void SomeDelegateType(params object[] args);
public class Program
{
public static void Main()
{
var dn = new DynamicMethod("foo", (Type)null, new[] {typeof(object[])});
var il = dn.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldc_I4_0);
il.Emit(OpCodes.Ldelem_Ref);
il.EmitCall(OpCodes.Call, typeof(Program).GetMethod("Function"), null);
il.Emit(OpCodes.Ret);
var action = (SomeDelegateType)dn.CreateDelegate(typeof(SomeDelegateType));

var obj = new SomeType();
action(obj);
}
public static void Function(object obj)
{
Type type = obj.GetType();
Console.WriteLine(type);
}
}

如果你不能有一个输入参数,那么你将不得不在你创建的类型上使用字段——这实际上正是编译器在你编写时所做的(例如)

object someObj = ...
Action action = () => Function(someObj);

创建为:

class <>somehorriblename {
public object someObj;
public void SomeGeneratedName() { Function(someObj); }
}
...
var captureClass = new <>somehorriblename();
captureClass.someObj = ...
Action action = captureClass.SomeGeneratedName;

关于c# - 将一个对象放在 ILGenerator 中的堆栈顶部,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4989681/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com