5

関数にオブジェクトのインスタンスを渡す必要があるため、明らかに、引数として取得するすべての情報を評価スタックにロードする必要があります。ここに私が探しているコードがあります

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 は、オブジェクトを引数として受け取る関数です。オブジェクトを関数に渡すことに成功し、それを操作してクラスをオブジェクトとして返すこともできます。

この例への参照はどこにも見つかりませんでした。MSDN で見つけただけです。何か間違っているのでしょうか、それとも欠点がありますか? あなたがそれを修正するか、より良い答えを提供できるかどうか、専門家にお願いします

4

4 に答える 4

5

リファレンスをリテラルILとしてコーディングしない限り、リファレンスを何もないところから抜き出すことはできません         。しないでください         b. をピン留めする必要があり、         c. しないでください。IntPtr


最善のアプローチは、作成しているメソッドのシグネチャによって異なります。それが静的で引数を取らない場合...まあ、それは少し注意が必要です。個人的には、生成されたメソッドにオブジェクトを渡し、そこから必要な外部データをデリゲートにフェッチさせる傾向があります。しかし、別の方法として、代わりにclassを生成し、型のフィールドにアクセスするインスタンス メソッドとしてメソッドを記述します。

違い (したがって私の好み) は、最初のメソッドには (せいぜい) メソッドのパラメーターが必要であり、 ;object[]を使用できることです。DynamicMethod2 つ目はMethodBuilderTypeBuilderModuleBuilderAssemblyBuilderなどを必要とするため、より多くの作業が必要になります。

私が言及する理由object[]は、一般に、生成されたメソッドに異なる入力が必要であっても、共通の署名が必要だからです。これにより、固定のデリゲート タイプにバインドし、より高速な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;
于 2011-02-14T07:26:34.273 に答える
4

私が使用した簡単な方法の 1 つは、GCHandleを取得し、それをIntPtr(静的メソッドGCHandle.ToIntPtrlongを介して) 取得し、それをorに変換することでしたinteger( ToPointerまたはToInt64を使用)。

そうすれば、 を呼び出すことができILGenerator.Emit(OpCodes.Ldc_I8, ptr)ました。

于 2016-02-28T05:30:44.693 に答える