2015-06-18 107 views
1

我想用反射調用每個類的方法,但我不能用指針作爲參考調用方法。通常情況下,我可以爲每個指針傳遞null,一切都會好的。問題是函數何時訪問我傳遞的指針。指針將是對內存地址0的引用,這對我的程序來說顯然是一個即時崩潰。 所以我需要一個指針傳遞給有效的內存ADRESS,但我不知道我怎麼可以在運行C#反射調用方法與參考/指針參數

我的代碼的壓縮版本中創建一個指針:

class Program 
{ 
    static void Main(string[] args) 
    { 
     var obj = new TestClass(); 
     var pointerMethod = obj.GetType().GetMethod("Test"); 
     var referenceMethod = obj.GetType().GetMethod("Test2"); 

     var pointerParameter = pointerMethod.GetParameters()[0]; 
     var referenceParameter = referenceMethod.GetParameters()[0]; 

     //Get the instance of the class that is referred by the pointer/reference 
     var pointerInstance = Activator.CreateInstance(pointerParameter.ParameterType.GetElementType()); 
     var referenceInstance = Activator.CreateInstance(referenceParameter.ParameterType.GetElementType()); 

     //Call the method and "cast" the char instance into an pointer 
     pointerMethod.Invoke(obj, new[] {pointerInstance.GetType().MakePointerType()}); 
     referenceMethod.Invoke(obj, new[] { referenceInstance.GetType().MakeByRefType() }); 
    } 
} 

而且識別TestClass:

public class TestClass 
{ 
     unsafe public void Test(char* pointer) 
     { 

     } 

     public void Test2(ref int reference) 
     { 

     } 
} 

我總是得到異常「System.RuntimeType」無法轉換爲類型'System.Char *' 奇怪的是,pointerInstance.GetType()。MakePointerType()返回一個char *,完全是什麼我必須通過樂趣ction ...

+2

您的方法聲明無效,以 - 您沒有提供參數類型。 ('ref'是一個修飾符,而不是一個類型。)如果你可以提供一個簡短的但完整的程序來演示這個問題,那將會有很大的幫助。此外,我建議你嘗試*只是* ref參數或*只是*指針參數 - 否則你不會知道哪一個失敗... –

+0

我編輯了我的文章並壓縮了代碼 – Djeurissen

+0

但仍未包含一個簡短但完整的程序,我可以簡單地複製,粘貼,編譯和運行。而'ref'版本的工作?如果是這樣,請將其刪除 - 最好專注於一個問題而不是兩個問題。 –

回答

8

首先,讓我們將其分解爲指針與ref - 它們的處理方式稍有不同。

目前還不清楚是什麼指針值你預期方法接受 - 尤其當你傳遞給Invoke是一個類型,而不是類型的實例值 - 但你應該使用Pointer.Box

using System.Reflection; 

class TestPointer 
{  
    unsafe static void Main() 
    { 
     char c = 'x'; 
     char* p = &c; 
     object boxedPointer = Pointer.Box(p, typeof(char*)); 

     var method = typeof(TestPointer).GetMethod("Foo"); 
     method.Invoke(null, new[] { boxedPointer }); 
     Console.WriteLine("After call, c = {0}", c); 
    } 

    public static unsafe void Foo(char *pointer) 
    { 
     Console.WriteLine("Received: {0}", *pointer); 
     *pointer = 'y'; 
    } 
} 

輸出:

Received: x 
After call, c = y 

對於ref參數,它是稍微簡單 - 你只允許正常的拳擊,和參數數組改變了:

using System.Reflection; 

class TestRef 
{  
    unsafe static void Main() 
    { 
     var method = typeof(TestRef).GetMethod("Foo"); 
     var args = new object[] { 10 }; 
     method.Invoke(null, args); 
     Console.WriteLine("After call, args[0] = {0}", args[0]); 
    } 

    public static unsafe void Foo(ref int x) 
    { 
     Console.WriteLine("Received: {0}", x); 
     x = 20; 
    } 
} 
+1

「指針」類的第一個很好的示例用法我見過:) – leppie

+2

@leppie:我從未在今天看過它:) –

+0

非常感謝。我總是忘記了我將Type的參數傳遞給了參數。但是我仍然有一個問題,如果我不知道我有哪種類型的指針,該怎麼辦?就像在我的例子中,我只有一個Object代表類型 – Djeurissen