2014-10-31 44 views
0

我想要做的是以下(我不知道它是否可能);我知道一個運行時間類型。我知道我想在運行時調用哪種方法。但是,我不知道這在編譯時間。C#在運行時創建參數類型未知的方法代理

由於inparam不是類型對象,因此GetFunction方法將無法創建給定methodInfo的委託。

有沒有辦法創建一個函數的委託,我只知道我希望委託的方法的Type和MethodInfo?

public sealed class Functions { 
    public static int SetStrValue(string s) { 
     // set a string 
    } 

    public static int SetIntValue(int i) { 
     // set an int 
    } 
} 

public sealed class GetFunctions { 
    public Func<object, int> GetFunction(Type type, MethodInfo methodInfo) { 
     // what I would like to do. 
     Func<object, int> func = Delegate.CreateDelegate(typeof(Func<object, int>), methodInfo); 
     return t => func(t); 
    } 
} 

public class InvokeFunctions { 
    public void invokeFunction() { 
     Type t = typeof(String); 
     MethodInfo methodInfo = typeof(Functions).GetMethod("SetStrValue"); 
     int i = GetFunctions.GetFunction(t, methodInfo).Invoke("hello"); 
    } 
} 
+0

問題本身的一面爲什麼你的課程是封閉的?這通常不是一個好主意,因爲它基本上說'我永遠不想擴展這個類或以任何方式改變它',而許多.NET類是封閉的,因爲.NET是框架,所以這樣做更有意義。你爲什麼要求你的密封? – sydan 2014-10-31 08:51:13

回答

3

您可以使用表達式樹來創建委託。由於編譯時類型未知,因此您可以嘗試在運行時將參數轉換爲適當的類型。

public sealed class GetFunctions 
{ 
    public static Func<object, int> GetFunction(MethodInfo methodInfo) 
    { 
     var obj = Expression.Parameter(typeof (object), "obj"); 
     var convert = Expression.Convert(obj, methodInfo.GetParameters().First().ParameterType); 
     var call = Expression.Call(methodInfo, convert); 
     var lambda = Expression.Lambda<Func<object, int>>(call, obj); 

     return lambda.Compile(); 
    } 
} 

public class InvokeFunctions 
{ 
    public void invokeFunction() 
    { 
     MethodInfo methodInfo = typeof(Functions).GetMethod("SetStrValue"); 
     int i = GetFunctions.GetFunction(methodInfo).Invoke("hello"); 

     MethodInfo methodInfo2 = typeof(Functions).GetMethod("SetIntValue"); 
     int i2 = GetFunctions.GetFunction(methodInfo2).Invoke(1); 
    } 
} 

我已經刪除了Type參數,並直接從方法的第一個參數採取它,如果這不是你可以改變它的預期的行爲。

+0

謝謝!有用。 :) – Ekenstein 2014-10-31 10:31:24

0

可以使用泛型來簡化這只是:

public sealed class Functions 
{ 
    public static int SetValue<T>(T input) 
    { 
     // set a value of type T 
    } 
} 

,並調用函數:

Functions.SetValue<string>("hello"); 

或者你可以使用一個通用的委託定義,如果你仍然想使用代表:

public delegate int MyDelegateFunction<T>(T input); 
+0

這意味着我需要在編譯時知道我推斷的類型。 這裏的主要問題是,我正在使用一個具有不同類型功能的API。 我想在這裏減少if語句。 在這種情況下,我必須在SetValue函數中檢查類型並根據類型調用正確的函數。 – Ekenstein 2014-10-31 08:55:42