zag*_*ski 5 .net il cil mono.cecil
是否可以编写通用CIL指令,将任何类型的实例(值和引用)转换为System.String?特别是,我对Mono.Cecil代码很感兴趣,它会将这些指令注入到方法中.
分析一个通用方法我想出了这些Mono.Cecil调用:(它应该将第i个方法参数转换为字符串)
System.Reflection.MethodInfo to_string_method_info = typeof( System.Object ).GetMethod( "ToString" );
Mono.Cecil.MethodReference to_string_reference = injectible_assembly.MainModule.Import( to_string_method_info );
Mono.Cecil.TypeReference argument_type = method_definition.Parameters[ i ].ParameterType;
method_definition.Body.Instructions.Add( processor.Create( Mono.Cecil.Cil.OpCodes.Constrained, argument_type ) );
method_definition.Body.Instructions.Add( processor.Create( Mono.Cecil.Cil.OpCodes.Callvirt, to_string_reference ) );
Run Code Online (Sandbox Code Playgroud)
但是,在调试时,我从注入的方法中获得"JIT编译器遇到内部限制"的异常.
编辑:
同样重要的是:注意我正在使用typeof(object).GetMethod(...),而不是typeof(T).GetMethod(...)- 你的线argument_type.GetType().GetMethod( "ToString" );看起来非常怀疑IMO.
我怀疑问题是你正在加载一个本地/参数,而不是本地/参数的地址 - 在显示之前的行中.Constrained需要这样才能正确执行静态调用实现; 对于虚拟调用实现,它可以简单地取消引用它以获得实际引用.
除此之外:Constrained应该工作正常 - 见下文(特别注意Ldarga_S).当然,另一种选择是使用Box,但这会产生更多的开销.Constrained是一种调用任意类型的理想方式ToString.
using System;
using System.Reflection.Emit;
public class RefTypeNoImpl { }
public class RefTypeImpl { public override string ToString() { return "foo"; } }
public struct ValTypeNoImpl { }
public struct ValTypeImpl { public override string ToString() { return "bar"; } }
static class Program
{
static void Main()
{
Test<RefTypeNoImpl>();
Test<RefTypeImpl>();
Test<ValTypeNoImpl>();
Test<ValTypeImpl>();
}
static void Test<T>() where T : new()
{
var dm = new DynamicMethod("foo", typeof(string), new[] { typeof(T) });
var il = dm.GetILGenerator();
il.Emit(OpCodes.Ldarga_S, 0);
il.Emit(OpCodes.Constrained, typeof(T));
il.Emit(OpCodes.Callvirt, typeof(object).GetMethod("ToString"));
il.Emit(OpCodes.Ret);
var method = (Func<T, string>)dm.CreateDelegate(typeof(Func<T, string>));
Console.WriteLine(method(new T()));
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
598 次 |
| 最近记录: |