2009-10-22 83 views
25

我有以下代碼:通用方法中執行一個運行時類型

public class ClassExample 
{ 

    void DoSomthing<T>(string name, T value) 
    { 
     SendToDatabase(name, value); 
    } 

    public class ParameterType 
    { 
     public readonly string Name; 
     public readonly Type DisplayType; 
     public readonly string Value; 

     public ParameterType(string name, Type type, string value) 
     { 
      if (string.IsNullOrEmpty(name)) 
       throw new ArgumentNullException("name"); 
      if (type == null) 
       throw new ArgumentNullException("type"); 

      this.Name = name; 
      this.DisplayType = type; 
      this.Value = value; 
     } 
    } 

    public void GetTypes() 
    { 
     List<ParameterType> l = report.GetParameterTypes(); 

     foreach (ParameterType p in l) 
     { 
      DoSomthing<p.DisplayType>(p.Name, (p.DisplayType)p.Value); 
     } 

    } 
} 

現在,我知道我不能執行DoSomething的() 有沒有使用此功能的任何其他方式?

回答

29

你可以,但它涉及反思,但你可以做到。

typeof(ClassExample) 
    .GetMethod("DoSomething") 
    .MakeGenericMethod(p.DisplayType) 
    .Invoke(this, new object[] { p.Name, p.Value }); 

這將着眼於包含類的頂部,獲得方法的信息,創建具有相應類型的通用方法,那麼你可以調用來調用它。

+0

只有一個catch,p.Value是一個字符串,所以調用將失敗,除非p.DisplayType碰巧是typeof(string)。 – stevemegson 2009-10-22 13:39:57

+1

慚愧這是唯一的解決方案,meh – 2009-11-16 21:54:58

+1

嗯,我想你可以在4.0中使用動態,它會推斷正確的泛型參數類型,但我還沒有機會驗證它。並不是說它在封面上做的和上面的代碼不同,但也許是這樣。 – 2009-11-16 22:11:11

5
this.GetType().GetMethod("DoSomething").MakeGenericMethod(p.Value.GetType()).Invoke(this, new object[]{p.Name, p.Value}); 

應該工作。

3

無法在運行時按照您希望的方式指定泛型類型。

最簡單的選擇是添加DoSomething的非通用超載,或者只需調用DoSomething<object>並忽略p.DisplayType。除非SendToDatabase取決於編譯時間類型的value(它可能不應該),那麼給它一個object應該沒有問題。

如果你不能做到這些,你將不得不使用反射來調用DoSomething,並且你將獲得巨大的性能。

1

嚴格地說你可以使用MethodInfo.MakeGenericMethod這個。

但我建議將DoSomething改爲非泛型形式,因爲它不是真的應該是通用的。

+0

我只是簡化了解釋程序。這實際上是最優雅的解決方案,信不信由你。 :) 謝謝! – Sarit 2009-10-22 12:57:36

3

首先,我們需要p.Value轉換爲正確的類型,因爲即使我們知道在編譯時的類型,我們不能將字符串傳遞直奔方法...

DoSomething<Int32>("10"); // Build error 

對於簡單的數字類型和日期時間,我們可以使用

object convertedValue = Convert.ChangeType(p.Value, p.DisplayType); 

現在我們可以使用反射來調用所需的通用方法...

typeof(ClassExample) 
    .GetMethod("DoSomething") 
    .MakeGenericMethod(p.DisplayType) 
    .Invoke(this, new object[] { p.Name, convertedValue }); 
相關問題