2010-08-05 6 views
3

Jusqu'à présent, je trouve que Linq peut être utilisé sur des champs existants et des propriétés d'une classe, pas sur des propriétés virtuelles. En d'autres termes, ITypedList ne peut pas travailler avec Linq, même par Linq dynamique.Comment faire Linq sur ITypedList?

J'ai essayé le code suivant:

IQueryable contact ; ... 

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

Ensuite, j'ai rencontré l'exception de "Non linkedPropertyName ou d'un champ 'Client' existe dans le type 'Contact'".

I tracée en Linq dynamique et trouvé le code suivant soulevé l'exception:

  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); 

dans le procédé d'expression ParseMemberAccess (type de type, par exemple d'expression).

Il est évident que seul le membre réel des champs et des propriétés est pris en charge dans Linq.

Mais je m'attends toujours à ce que quelqu'un ait trouvé un moyen de faire Linq sur les propriétés virtuelles.

Si vous trouvez un moyen de le faire, partagez votre expérience.

Nous vous remercions à l'avance,

Ying

Répondre

2

Ce code est pas beaucoup mieux que le code que vous écririez sans expressions LINQ, mais ici il va.

Ce code suppose que votre ITypedList est également un IList. Obtient un descripteur de propriété pour la propriété désirée et teste chaque élément de la collection en faisant ce qui équivaut à une liste (int i = 0; i < ((ICollection)) .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); 
Questions connexes