次のコードでは、ランタイムのデステージビリティが発生する可能性があるという例外が発生します。 Opcodes.CallVirtへOpcodes.Call
を変更なぜコール命令がランタイムのデステージビリティをもたらすのですか?
var method = new DynamicMethod("CallObjectToString", typeof(string),new[]{ typeof(object)});
var ilgen =method.GetILGenerator();
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Call, typeof(object).GetMethod("ToString"));
ilgen.Emit(OpCodes.Ret);
var @delegate = method.CreateDelegate(typeof(Func<object, string>)) as Func<object,string>;
@delegate(new object());
は、問題を修正します。 これはすべてうまくできていますが、typebuilderを使用して、という正確なのILを持つ(MethodBuilder)を使用して構築された静的メソッドを作成し、CreateDelegateを使用してこの例外をスローしません。実際にはメソッドビルダーを使って、型が継承しているものではなく、まったく別のオブジェクトの仮想メソッドで何かを呼び出すことができます。さらに不可解私はnew object().ToString()
ような何かを行う場合、それはまた、むしろcallvirt
よりも、ILにcall
命令を発することは何
。
call
を使用して仮想メソッドを呼び出すことは無効ですが、インスタンスのオーバーライドで基本メソッドを呼び出す場合を除いて、CLRではそのようなメソッドを静的に別の型にすることはできますか?または、既知の非ヌルエンティティに対してcall
命令を発行することを許可しますか?
これはDynamicMethod
で生成されたコードの唯一の問題ですか?
編集: 私は本当に気にしないので、パフォーマンスの観点からは求めていません。以下のコードは、不安定化アクションを実行するデリゲートを作成し、ランタイムを不安定にすることはありません。これが問題の全体です。なぜ1つは合法で、もう1つは違法ですか?
var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("SomeAssembly"), AssemblyBuilderAccess.Run) ;
var moduleBuilder = assemblyBuilder.DefineDynamicModule("SomeModule");
var typeBuilder = moduleBuilder.DefineType("SomeType");
var methodBuilder = typeBuilder.DefineMethod("SomeStaticMethod",MethodAttributes.Public | MethodAttributes.Static,typeof(string),new[]{typeof(object)});
var ilgen = methodBuilder.GetILGenerator();
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Call, typeof(object).GetMethod("ToString"));
ilgen.Emit(OpCodes.Ret);
var newType = typeBuilder.CreateType();
var @delegate = Delegate.CreateDelegate(typeof(Func<object, string>),newType.GetMethod("SomeStaticMethod")) as Func<object,string>;
@delegate(new object());
これは当てはまりますが、なぜ型生成ツールでReflection Emitを使用して生成するコードで許可されているのですか?実際にはオブジェクトのオーバーロードを呼び出すわけではありませんが、実際には直接呼び出しを行います。 –
私が言うことができるのは、Reflection.Emitは、あなたが何をしているのかをあなたが知っていると仮定しているということです。ここでの直接呼び出しがどのように深刻な方法でランタイムを不安定にすることができるかわかりませんが、DynamicMethodがあなたを保護しようとしている最初のインスタンスではそうです。確かめるのは難しいです。 – Stewart