2013-08-12 21 views
5

Có thể viết hướng dẫn CIL chung sẽ chuyển đổi các thể hiện của bất kỳ loại nào (cả giá trị và tham chiếu) thành System.String? Cụ thể, tôi quan tâm đến mã Mono.Cecil sẽ đưa các lệnh đó vào một phương thức.Có mã CIL chung nào để chuyển đổi bất kỳ thể hiện kiểu nào thành chuỗi không?

Phân tích một phương pháp chung tôi đã đưa ra những Mono.Cecil gọi: (đó là nghĩa vụ để chuyển đổi các tham số phương pháp thứ i đến chuỗ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)); 

Tuy nhiên, khi gỡ lỗi tôi nhận được một ngoại lệ từ phương pháp tiêm mà "trình biên dịch JIT gặp phải giới hạn nội bộ".

+1

Trong trường hợp như thế này, PEVerify có thể rất hữu ích, vì nó có thể cho bạn biết mã lỗi cụ thể của bạn có. – svick

Trả lời

8

Edit:

Cũng quan trọng: lưu ý rằng tôi đang sử dụng typeof(object).GetMethod(...), không typeof(T).GetMethod(...) - dòng bạn argument_type.GetType().GetMethod("ToString"); trông rất nghi ngờ IMO.


tôi nghi ngờ vấn đề là bạn đang tải một local/tranh luận, chứ không phải là địa chỉ của một địa phương/đối số - trong dòng ngay trước những gì được hiển thị. Constrained cần điều này để nó có thể thực hiện chính xác việc thực hiện cuộc gọi tĩnh; để thực hiện cuộc gọi ảo, nó có thể chỉ đơn giản là dereference này để có được tham chiếu thực tế.

Khác hơn: Constrained sẽ hoạt động tốt - xem bên dưới (đặc biệt, lưu ý Ldarga_S). Tất nhiên, một tùy chọn khác là sử dụng Box, nhưng điều này sẽ có nhiều chi phí hơn. Constrained là cách lý tưởng cách gọi ToString tùy theo loại tùy ý.

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

Đó chính xác là những gì tôi đã làm: Ldarg thay vì Ldarga. – zagrobelski

+0

@zagrobelski không phải là một dự đoán xấu; p –

Các vấn đề liên quan