2015-06-26 47 views
3

我正在嘗試構建OrderBy表達式問題是,當我將var對象傳遞給TSource時,TSource類型將是對象而不是實際列類型 例如,Actual類型是int,但TSource類型是object 。將var作爲T參數傳遞

Type tblType = tblObj.GetType(); 
PropertyInfo propinfo; 
propinfo = tblType.GetProperty(ColumnName); 
if (propinfo == null) 
{ 
    return null; 
} 
var instance = Activator.CreateInstance(propinfo.PropertyType); 
result = result.OrderBy(GetOrder(item.ColumnName, tblObj, instance)); 

和這裏是λ表達式構建器

public Expression<Func<T, TSource>> GetOrder<T,TSource>(string field, T item,TSource source) 
    { 
     if (string.IsNullOrEmpty(field)) 
     { 
      return null; 
     } 
     var param = Expression.Parameter(typeof(T), "c"); 
     Expression conversion = Expression.Convert(Expression.Property 
     (param, field), typeof(TSource)); 
     return Expression.Lambda<Func<T, TSource>>(conversion, param); 
    } 
+2

請注意,沒有'var'對象或'var'類型。 'var'僅僅意味着編譯器推斷出這個類型,所以你在聲明一個變量時不必明確寫下它。 'Activator.CreateInstance'返回'object',所以你的行等於'object instance = Activator.CreateInstance(propinfo.PropertyType);'。 – sloth

回答

2

您必須使用dynamic關鍵字或使用反射。 但是,您可以更輕鬆地用dynamic解決您的問題。 唯一的問題是,擴展方法不會被動態調度。 所以,你必須調用擴展方法,簡單的靜態方法:

result = Enumerable.OrderBy(
      result, 
      GetOrder(item.ColumnName, tblObj, instance as dynamic)); 

此外,你可以問一個問題「?爲什麼擴展方法不能被動態調度」

asnwer by @EricLippert

這意味着,爲了獲得一個動態的擴展方法調用 正確解析,不知何故DLR必須知道在所有 命名空間嵌套和「用」什麼指令是運行在你的源碼 的代碼中。我們沒有用於將所有 信息編碼到呼叫站點的機制。我們考慮制定這樣一個 機制,但決定它太高的成本,併產生太多的時間表風險值得。

因此,CLR必須找到包含擴展方法的名稱空間。 CLR搜索它,它找到方法名稱空間,然後它只是變化,例如,result.OrderByEnumerable.OrderBy(result, ...)。但是,在dynamic關鍵字的情況下,DLR(動態語言運行時)必須在運行時再次根據所包含的名稱空間找到此方法的類。微軟團隊正確認爲它是太高的成本,並避免實施它。

0
方法

Activator.CreateInstance(Type type)返回Object,不是int。 可能你應該在使用前將它解除爲int狀態;

0

按照文檔Activator.CreateInstance返回的對象,所以你必須將它轉換爲目標類型,也可以使用dynamic型,但比編譯器不能檢查的類型。

4

如果不確定該類型,則可以使用dynamic,以便在運行時級別找到該類型。

result = Enumerable.OrderBy(
     result, 
     GetOrder(item.ColumnName, tblObj, (dynamic)instance)); 
+1

最後,'動態'的合法用法* *不會覺得自己像一個黑客! – Gusdor