2013-02-10 29 views
5

Tôi muốn phát ra một phương pháp có biến số mà tôi có thể thực hiện. Nhưng, tôi muốn lưu trữ trong biến đó một đối tượng MethodInfo, đó là một tham chiếu đến một phương thức khác (không được phát ra).Làm cách nào để phát ra phương thức có biến cục bộ MethodInfo được tải sẵn?

Tôi có thể phát ra các opcodes để gọi typeof (someClass) .GetMethod (...), nhưng sẽ hiệu quả hơn nếu tôi chỉ cần tải một mã thông báo cho MethodInfo này và đưa nó trực tiếp vào biến. Vì vậy, để rephrase, tôi đang cố gắng để tìm ra của nó có thể phát ra, hãy nói một "load object" opcode và vượt qua nó một đối tượng lúc emit-thời gian đó sẽ được nạp vào stack lúc runtime. (OpCodes.Ldobj đã đưa ra một số loại lỗi khi tôi thử điều này). Hoặc, tôi buộc phải phát ra các opcodes sẽ làm điều này trong thời gian chạy?

+0

Tôi nghĩ điều này là có thể. Eric Lippert từng viết blog về một nhà điều hành C# có thể sử dụng điều này. – usr

+0

Bạn có thể đưa ra một bối cảnh nhỏ về lý do đằng sau, để làm cho vấn đề một chút rõ ràng hơn cho tôi/chúng tôi? –

+0

@usr [Bài viết bạn đang nói về] (http://blogs.msdn.com/b/ericlippert/archive/2009/05/21/in-foof-we-trust-a-dialogue.aspx) là về các vấn đề cú pháp của 'infoof', không phải cách nó có thể được thực hiện. – svick

Trả lời

8

Bạn không thể tải bất kỳ đối tượng chung nào trong IL, bởi vì không có cách nào để lưu trữ nó trong IL (ngoại trừ một số loại đặc biệt như string). Bạn có thể làm việc xung quanh đó bằng cách sử dụng serialization (cho các loại hỗ trợ nó), nhưng tôi không nghĩ rằng đó là những gì bạn muốn. Ngoài ra, ldobj phục vụ một mục đích khá khác nhau.

Nhưng bạn có thể làm điều này cho MethodInfo theo cách rất giống với những gì C# thực hiện cho toán tử typeof. Điều đó có nghĩa:

  1. bằng cách sử dụng hướng dẫn ldtoken để có được một RuntimeMethodHandle
  2. gọi MethodBase.GetMethodFromHandle() để có được một dàn diễn viên MethodBase
  3. nó để MethodInfo

Toàn bộ mã để tạo ra một phương thức trả về MethodInfo có thể trông giống như sau:

MethodInfo loadedMethod = …; 
var getMethodMethod = typeof(MethodBase).GetMethod(
    "GetMethodFromHandle", new[] { typeof(RuntimeMethodHandle) }); 

var createdMethod = new DynamicMethod(
    "GetMethodInfo", typeof(MethodInfo), Type.EmptyTypes); 

var il = createdMethod.GetILGenerator(); 
il.Emit(OpCodes.Ldtoken, loadedMethod); 
il.Emit(OpCodes.Call, getMethodMethod); 
il.Emit(OpCodes.Castclass, typeof(MethodInfo)); 
il.Emit(OpCodes.Ret); 

var func = (Func<MethodInfo>)createdMethod.CreateDelegate(typeof(Func<MethodInfo>)); 
Console.WriteLine(func()); 
+0

Đã hoạt động hoàn hảo! –

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