2017-04-19 62 views
2

我今天有一個靜態函數,我通過房產表達,我從它創建一個字符串:傳遞蘭巴表達式列表訪問屬性

public static string SomeFunction<TModel, TProperty>(TModel model, Expression<Func<TModel, TProperty>> expression){...} 

我想改變它來處理列表這樣的表達式:

static string SomeFunctionForList<TModel, TProperty>(TModel model, List<Expression<Func<TModel, TProperty>>> expressions){...} 

在第二種情況下,我會循環表達式並執行我在其上執行的任何邏輯。

這就是我現在如何調用該函數:

SomeFunction(this, m => m.nameOfProperty) 

我如何調用該函數,定義表達式的一個列表?我想這一點,但它不工作:

SomeFunctionForList(this, 
        new List<Expression<Func<TModel, TProperty>>> { 
         { m => m.nameOfProperty1}, 
         { m => m.nameOfProperty2} 
}); 

我收到的TModel和TProperty無法找到一個編譯器錯誤。清楚的是,這在另一個文件中被調用。

+0

我不知道,但我的意思是「TModel的」和「TProperty」不是類型。它們是通用參數。你必須用任何模型類型替換「TModel」,用任何屬性類型替換「TProperty」。 –

+0

您遇到的問題是每個產權的「TProperty」都會有所不同? – DavidG

+0

耶 - 基本上,我想發送一個模型和一個lamba表達式列表,並讓該方法發揮其魔力 – Corez

回答

1

你有一般方法SomeFunctionForList與通用類型參數TModelTProperty。在第一種情況下,類型推斷能夠從方法調用的第一個和第二個參數中推斷出這些參數的類型。這就是爲什麼你可以直接跳過指定類型參數。

但類型推斷僅適用於泛型方法。它不適用於從構造函數參數推斷類型參數。這就是爲什麼你應該明確指定List<T>泛型參數。注意:您應該指定類型名稱而不是通用參數。例如。如果TModelYourModel類,和兩個屬性有string類型,然後調用方法應該是這樣的:

SomeFunctionForList(this, 
      new List<Expression<Func<YourModel, string>>> { 
        { m => m.nameOfProperty1}, 
        { m => m.nameOfProperty2} 
      }); 

所以,列表構造函數的用法是不是如果你想使用類型推斷一個不錯的選擇。您可以使用params指定數目可變的參數(這是作爲一個數組傳遞),並有類型推斷的好處:

public static string SomeFunction<TModel, TProperty>(
    TModel model, params Expression<Func<TModel, TProperty>>[] expressions) 

隨後的方法調用看起來像

SomeFunctionForList(this, 
       m => m.nameOfProperty1, 
       m => m.nameOfProperty2 
      ); 

注意,性能應有相同的類型。

+0

Gotcha - 在現實生活中,我有幾個參數後,在方法中的所以參數不是一個理想的選擇。有什麼辦法可以欺騙編譯器進行跳過類型推斷嗎? – Corez

+1

@Corez你不能使用構造函數 - 類型推斷在這裏不起作用。您可以創建工廠,通過一般方法爲您創建清單。同樣的方法用於元組 - 而不是調用'新元組(4,「foo」)''你可以調用工廠方法'Tuple.Create(4,「foo」)'。你的工廠可以簡單的作爲'公共靜態列表 CreateList (params T [] items)=> items.ToList();'和用法將'SomeFunctionForList(this,Factory.CreateList(m => m.nameOfProperty1,m => m.nameOfProperty2))' –

0
public static string SomeFunction<TModel, TProperty>(TModel model, params Expression<Func<TModel, TProperty>>[] expressions) 
+0

我應該已經更清楚了 - 我的意思是當我調用該函數時發生該問題。在那個文件中,它不能識別TModel和TPropoerty – Corez

+0

你必須打開這些方法,並使用反射來計算通用參數,以便成功地調用它們。 如果沒有方法源代碼,很難猜測錯誤。但我認爲你應該能夠通過反思做到這一點。 –

+0

錯誤是一個編譯錯誤,調用者無法編譯,因爲無法找到TModel和TProperty。很明顯,因爲它們是調用代碼範圍之外的泛型。 – Corez

1

「TModel」和「TProperty」是通用參數,不是類型。但是如果你想調用它,你必須輸入任何模型類型和任何屬性類型。

例如,這應該工作:

private string aStringProperty { get; set; } 
private int aIntegerProperty { get; set; } 

-

SomeFunctionForList(this, new List<Expression<Func<Program, dynamic>>>{ 
                   { m => m.aStringProperty}, 
                   { m => m.aIntegerProperty} 
                  }); 

在我的情況,我用了一個動態的屬性。有了這個,你可以使用不同類型的屬性,但要小心!

1

您需要指定類型的參數,例如:

​​

但是,這僅允許您使用所有返還相同種類,在這種情況下string性能。你可以使用object代替:

SomeFunctionForList(t, 
       new List<Expression<Func<Thing, object>>> { 
        { m => m.StringProperty}, 
        { m => m.BoolProperty} 
});