2010-08-05 42 views
3

到目前爲止,我發現Linq可以在類的現有字段和屬性上使用,而不是在虛擬屬性上使用。換句話說,即使通過動態Linq,ITypedList也不能用於Linq。如何在ITypedList上執行Linq?

我嘗試下面的代碼:

IQueryable contact ; ... 

    dynamic l = contact.Select("Customer.Name as Name"); 
    // Customer is a virtual property provided by the interface of ITypedList. 

然後,我遇到了「不linkedPropertyName或字段‘客戶’存在型‘聯繫’」的例外。

我追查到動態LINQ和發現下面的代碼引發的異常:

  MemberInfo member = FindPropertyOrField(type, id, instance == null); 
      if (member == null) 
       throw ParseError(errorPos, Res.UnknownPropertyOrField, 
        id, GetTypeName(type)); 
      return member is PropertyInfo ? 
       Expression.Property(instance, (PropertyInfo)member) : 
       Expression.Field(instance, (FieldInfo)member); 

在表達式ParseMemberAccess(類型類型,表達式實例)的方法。

很明顯只有Linq中支持字段和屬性的真實成員。

但我仍然期望有人可能已經找到了在虛擬屬性上執行Linq的方法。

如果您找到一種方法,請分享您的經驗。

謝謝你在前進,

回答

2

這段代碼並不比代碼你沒有LINQ表達式寫出更好的,但在這裏不言而喻。

此代碼假定您的ITypedList也是IList。獲取期望屬性的屬性描述符,並通過做一個for(int i = 0; i <((ICollection)list).Count; i ++) { ... }

 ParameterExpression listParameter = Expression.Parameter(
      typeof(ITypedList), 
      "list" 
     ); 
     ParameterExpression propertyDescriptorVariable = Expression.Variable(
      typeof(PropertyDescriptor), 
      "propertyDescriptor" 
     ); 
     ParameterExpression indexVariable = Expression.Variable(
      typeof(int), 
      "index" 
     ); 
     ParameterExpression resultVariable = Expression.Variable(
      typeof(bool), 
      "result" 
     ); 
     LabelTarget @break = Expression.Label(); 
     Expression<Func<ITypedList, bool>> lambdaExpression = Expression.Lambda<Func<ITypedList, bool>>(
      Expression.Block(
       new[] { propertyDescriptorVariable, indexVariable, resultVariable }, 
       Expression.Assign(
        propertyDescriptorVariable, 
        Expression.Property(
         Expression.Call(
          listParameter, 
          typeof(ITypedList).GetMethod(
           "GetItemProperties", 
           BindingFlags.Instance | BindingFlags.Public 
          ), 
          Expression.Default(
           typeof(PropertyDescriptor[]) 
          ) 
         ), 
         typeof(PropertyDescriptorCollection).GetProperty(
          "Item", 
          typeof(PropertyDescriptor), 
          new[] { typeof(string) } 
         ), 
         Expression.Constant(
          "Name" 
         ) 
        ) 
       ), 
       Expression.Assign(
        indexVariable, 
        Expression.Constant(
         0, 
         typeof(int) 
        ) 
       ), 
       Expression.Assign(
        resultVariable, 
        Expression.Constant(
         true 
        ) 
       ), 
       Expression.Loop(
        Expression.IfThenElse(
         Expression.LessThan(
          indexVariable, 
          Expression.Property(
           Expression.Convert(
            listParameter, 
            typeof(ICollection) 
           ), 
           "Count" 
          ) 
         ), 
         Expression.IfThenElse(
          Expression.Equal(
           Expression.Constant(
            null 
           ), 
           Expression.Call(
            propertyDescriptorVariable, 
            "GetValue", 
            Type.EmptyTypes, 
            Expression.Property(
             Expression.Convert(
              listParameter, 
              typeof(IList) 
             ), 
             "Item", 
             indexVariable 
            ) 
           ) 
          ), 
          Expression.Block(
           Expression.Assign(
            resultVariable, 
            Expression.Constant(
             false 
            ) 
           ), 
           Expression.Break(
            @break 
           ) 
          ), 
          Expression.PostIncrementAssign(
           indexVariable 
          ) 
         ), 
         Expression.Break(
          @break 
         ) 
        ), 
        @break 
       ), 
       resultVariable 
      ), 
      listParameter 
     ); 
     bool isEveryNameNotNull = lambdaExpression.Compile().Invoke(list);