是否有通用CIL代码将任何类型实例转换为字符串? [英] Is there a generic CIL code to convert any type instance to string?

查看:90
本文介绍了是否有通用CIL代码将任何类型实例转换为字符串?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以编写将任何类型(值和引用)的实例转换为System.String的通用CIL指令?
特别是我对Mono.Cecil代码感兴趣,该代码会将这些指令注入到方法中。

Is it possible to write generic CIL instructions which will convert instances of any type (both value and reference) to System.String? In particular, I'm interested in Mono.Cecil code which will inject those instructions into a method.

分析我想到的这些Mono的通用方法.Cecil调用:
(应该将第i个方法参数转换为字符串)

Analyzing a generic method I came up with these Mono.Cecil calls: (it's supposed to convert the i-th method parameter to string)

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 ) );

但是,在调试时,我从注入的方法中得到了一个例外,即 JIT编译器遇到内部限制 。

However, when debugging I get an exception from the injected method that the "JIT compiler encountered internal limitation".

推荐答案

编辑:

也很重要:请注意,我是使用 typeof(object).GetMethod(...),而不是 typeof(T).GetMethod(...)-您的行 argument_type.GetType()。GetMethod( ToString); 看起来非常可疑IMO。

Also important: note that I am using typeof(object).GetMethod(...), not typeof(T).GetMethod(...) - your line argument_type.GetType().GetMethod( "ToString" ); looks very suspect IMO.

我怀疑问题是您正在加载本地/参数,而不是本地/参数的地址-在行之前显示的内容。 Constrained 需要此功能,以便它可以正确执行静态调用实现;对于虚拟呼叫实现,它可以简单地取消引用以获得实际引用。

I suspect the issue is that you are loading a local/argument, rather than the address of a local/argument - in the line immediately before what is shown. Constrained needs this so that it can correctly perform the static-call implementation; for the virtual-call implementation, it can simply dereference this to get the actual reference.

除此之外:约束应该可以正常工作-参见下文(特别注意 Ldarga_S )。当然,另一个选择是使用 Box ,但这会产生更多开销。 约束是在任意类型上调用 ToString 理想方法。

Other than that: Constrained should work fine - see below (in particular, note the Ldarga_S). Of course, another option is to use Box, but this will have more overhead. Constrained is the ideal way of calling ToString on an arbitrary type.

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()));
    }
}

这篇关于是否有通用CIL代码将任何类型实例转换为字符串?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆