到目前为止,我发现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.
然后,我遇到了“联系人”类型中存在“没有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);
在Expression ParseMemberAccess(Type type,Expression instance)的方法中。
很明显,Linq只支持字段和属性的真实成员。
但我仍然希望有人可能找到了在虚拟财产上做Linq的方法。
如果您有办法,请分享您的经验。
提前谢谢你,
应
答案 0 :(得分: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);