4

到目前为止,我发现 Linq 可以用于类的现有字段和属性,而不是虚拟属性。换句话说,ITypedList 不能与 Linq 一起工作,即使是动态 Linq。

我尝试了以下代码:

    IQueryable contact ; ...

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

然后,我遇到了“'Contact'类型中不存在linkedPropertyName或'Customer'字段”的异常。

我跟踪到动态 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);

在 Expression ParseMemberAccess(Type type, Expression instance) 的方法中。

很明显,Linq 只支持字段和属性的真实成员。

但我仍然希望有人可能已经找到了一种在虚拟属性上执行 Linq 的方法。

如果您找到了方法,请分享您的经验。

先感谢您,

4

1 回答 1

3

这段代码并不比你在没有 linq 表达式的情况下编写的代码好多少,但它就在这里。

此代码假定您的 ITypedList 也是 IList。获取所需属性的属性描述符并通过执行相当于 a 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);
于 2011-02-24T16:18:44.850 回答