2011-06-17 52 views
3

另一個對象的屬性我有這樣兩類:Lambda表達式來訪問對象的屬性,在C#中

public class Contratos 
{ 
//... 
    public int EntidadeFinanceiraId { get; set; } 
    [Column("Nome")] 
    public EntidadesFinanceiras entidadeFinanceira { get; set; } 
//... 
} 

public class EntidadesFinanceiras 
{ 
    [Key] 
    public int ID { get; set; } 
    public string Nome { get; set; } 
//... 
} 

,並希望dinamically過濾Contratos的基礎上Contratos.entidadeFinanceira.Nome列表。這是基於用戶選擇的屬性過濾列表的方法的一部分。

public IQueryable<Models.Contratos> applyLambdaFilter(string val, string col, string oper, IQueryable<Models.Contratos> contratosList) 
    { 
     if (!string.IsNullOrWhiteSpace(val)) 
     { 
      string typeName; 
      string columnName; 
      Type propType; 
      string[] propName = col.Split(new[] { '.' }); 
      if (propName.Count() > 1) 
      { 
       typeName = "GAcordos.Models." + propName[0]; //entidadeFinanceira 
       columnName = propName[1]; //Nome 
       propType = Type.GetType("GAcordos.Models.Contratos").GetProperty(propName[0]).PropertyType.GetProperty(columnName).PropertyType; //String 
      } 
      else 
      { 
       typeName = "GAcordos.Models.Contratos"; 
       columnName = propName[0]; //Other Contratos property 
       propType = Type.GetType(typeName).GetProperty(columnName).PropertyType; 
      } 
      if (propType != null) 
      { 
       var fixedItem = Comparators.getFixedItemWithType(val, propType); 
       var param = Expression.Parameter(typeof(GAcordos.Models.Contratos), "x"); 
       var body = Expression.Equal(Expression.PropertyOrField(param, col.ToString()), fixedItem, false, Type.GetType("GAcordos.Helpers.Comparators").GetMethod(oper, new Type[] { propType, propType })); 
       var lambda = Expression.Lambda<Func<GAcordos.Models.Contratos, bool>>(body, param); 
       contratosList = contratosList.Where(lambda.Compile()).AsQueryable(); 
      } 
     } 
     return contratosList; 
    } 

當該方法執行它拋出異常「entidadeFinanceira.Nome」不是類型就行「GAcordos.Models.Contratos」的成員

var body = Expression.Equal(Expression.PropertyOrField(param, col.ToString()), fixedItem, false, Type.GetType("GAcordos.Helpers.Comparators").GetMethod(oper, new Type[] { propType, propType })); 

但是,如果我寫直接表達:

contratosList = contratosList.Where(x => x.entidadeFinanceira.Nome == val); 

它工作正常。

那麼,我該如何構建lambda表達式x => x.property.property == constVal?

回答

3

簡單地說,您需要PropertyOrField的兩種用法。

手動構造,x => x.Foo.Bar == constVal是:

var param = Expression.Parameter(typeof(ObjectType), "x"); 
var lambda = Expression.Lambda<Func<ObjectType, bool>>(
    Expression.Equal(
     Expression.PropertyOrField(
      Expression.PropertyOrField(param, "Foo"), "Bar" 
     ), Expression.Constant(constVal, constValType) 
    ), param); 

(注意,包括constValType的情況下,重要constValnull;這避免了很多意想不到的問題)

+0

(注意我'掩飾*捕獲*`constVal`和顯式*常數*之間的區別......但是:meh) – 2011-06-17 11:29:48

0

似乎調用

Expression.PropertyOrField(param, col.ToString()) 

變量col包含「ent idadeFinanceira.Nome」。您可以重複使用的所有分裂col上面一樣,做一些事情,如:

Expression property = param; 
foreach(var pName in propName) { 
    property = Expression.PropertyOrField(property, pName); 
} 

現在表達property應該是正確的,你可以用它來構建body表達:

var body = Expression.Equal(
    property, 
    fixedItem, 
    false, 
    Type 
     .GetType("GAcordos.Helpers.Comparators") 
     .GetMethod(oper, new Type[] { propType, propType }) 
    );