2011-01-29 31 views
8

Tiêu đề nhiều hay ít nói lên tất cả. Dựa trên this bài viết, tôi đã đi lên với điều này:Làm thế nào để tiêm IL vào một phương pháp tại thời gian chạy

public static unsafe void Replace(this MethodBase destination, MethodBase source) 
{ 
    IntPtr srcHandle = source.MethodHandle.GetFunctionPointer(); 
    IntPtr dstHandle = destination.MethodHandle.GetFunctionPointer(); 

    int* dstPtr = (int*)dstHandle.ToPointer(); 
    *dstPtr = srcHandle.ToInt32(); 
} 

này thực sự hoạt động ... thỉnh thoảng -.-

Ví dụ, các công trình này.

public static class Program 
{ 
    public static void Main(string[] args) 
    { 
     MethodInfo methodA = typeof(Program).GetMethod("A", BindingFlags.Public | BindingFlags.Static); 
     MethodInfo methodB = typeof(Program).GetMethod("B", BindingFlags.Public | BindingFlags.Static); 

     methodA.Replace(methodB); 

     A(); 
     B(); 
    } 

    public static void A() 
    { 
     Console.WriteLine("Hai World"); 
    } 

    public static void B() 
    { 
     Console.WriteLine("Bai World"); 
    } 
} 

Tuy nhiên, điều này không (SEHException). Tất cả những gì tôi đã làm là thay đổi thứ tự các hàm được định nghĩa.

public static class Program 
{ 
    public static void Main(string[] args) 
    { 
     MethodInfo methodA = typeof(Program).GetMethod("A", BindingFlags.Public | BindingFlags.Static); 
     MethodInfo methodB = typeof(Program).GetMethod("B", BindingFlags.Public | BindingFlags.Static); 

     methodA.Replace(methodB); 

     A(); 
     B(); 
    } 

    public static void B() 
    { 
     Console.WriteLine("Bai World"); 
    } 

    public static void A() 
    { 
     Console.WriteLine("Hai World"); 
    } 
} 

Đối với mã trong bài viết ... Tôi không thể làm việc đó được.

Bất kỳ ý tưởng/lựa chọn thay thế nào?

+0

Tại sao bạn muốn thực hiện việc này? Điều này nghe có vẻ như một ý tưởng khủng khiếp. – Amy

+2

Đừng lo lắng - không có gì độc hại. Chỉ vì lợi ích của kiến ​​thức: D – YellPika

+0

Tôi tin rằng cách an toàn duy nhất để làm điều này là tiêm mã trước khi lắp ráp được nạp. – porges

Trả lời

8

Điều này khiến rất nhiều giả định xấu sẽ khiến bạn bị lừa.

Điều đầu tiên trước tiên, cấu trúc được trả về thông qua phản chiếu không được đảm bảo, theo bất kỳ cách nào, để trỏ đến bất kỳ cấu trúc thời gian chạy nào cả. Như vậy cố gắng để sửa đổi các con trỏ nó chứa hoặc trả về chỉ là đồng bằng sai. Thứ hai, nếu bạn muốn làm một cái gì đó như tiêm trước/sau phương pháp gọi bất biến (ví dụ) thì có lẽ bạn nên xây dựng các đối tượng proxy thời gian chạy và tiêm những thay thế đó. Hoặc sử dụng xây dựng phương thức động thông qua không gian tên Emit. Cố gắng thao tác mọi thứ thông qua các hành vi không có giấy tờ/không xác định (chẳng hạn như mã ở trên) sẽ không hoạt động.

Bạn cũng cần phải nhận ra rằng JIT quyết định khi nào nó sẽ chạy. Đôi khi nó chạy trên toàn bộ một lớp, và đôi khi nó chỉ chạy với một phương thức duy nhất. Mã của bạn không cố gắng xác định xem phương thức đã được JITted chưa, và mù quáng giả định rằng con trỏ hàm trả về có thể được sửa đổi.

+0

Tôi yêu tên và tôi yêu chương trình. Chúc một ngày tốt lành! – Amy

+0

Trong trường hợp đó ... a) Vì vậy, chính xác những gì nó trỏ đến sau đó? b) Làm thế nào để tôi tìm ra một phương pháp đã được JITted? – YellPika

+0

b) bạn không thể, trừ khi chương trình được xử lý thông qua NGen trước khi thực thi. – Amy

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