我所拥有的是一个List<string> IndexFields
,其中包含属性名称列表。
我的问题是我需要根据列表中的元素构建一个where子句。
到目前为止,我有;
var sitem = List1.Where(p => (p.GetType().GetProperty(IndexFields[0])
.GetValue(p, null) as string) == "red").FirstOrDefault();
但这仅允许我指定一个属性。我需要的是一个可以基于
List<string> IndexFields
列表中所有名称进行构建的构建器。 最佳答案
在运行时创建动态查询的最灵活的方法是使用Expression API:
例如:-
var type = typeof(T);
var properties = IndexFields.Select(x => type.GetProperty(x));
// x
var paramter = Expression.Parameter(type);
// x.Foo, x.Bar, ...
var leftHandSides = properties.Select(
x => Expression.Property(parameter, x));
// "Baz"
var rightHandSide = Expression.Constant(...);
// x.Foo == "Baz", x.Bar = "Baz", ...
var equalityExpressions = leftHandSides.Select(
x => Expression.Equal(x, rightHandSide));
// x.Foo == "Baz" && x.Bar == "Baz" && ...
var aggregatedExpressions = equalityExpressions.Aggregate(
(x, y) => Expression.AndAlso(x, y));
// x => x.Foo == "Baz" && x.Bar == "Baz" && ...
var lambda = Expression.Lambda<Func<T,bool>>(
aggregatedExpressions, parameter)
var item = List1.Where(lambda).FirstOrDefault();
建立这样的查询的一个巨大优势是,结果表达式仍然可以是转换为SQL以便与Entity Framework一起使用时,在lambda主体内部使用反射的限制确实很有限。
我确实建议您在使用它之前花一些时间来真正理解表达式框架。如果您可以了解正在发生的事情,从长远来看,它可以为您节省大量时间。
您可以在以下位置阅读更多信息:-
http://www.digitallycreated.net/Blog/37/dynamic-queries-in-entity-framework-using-expression-trees
https://stackoverflow.com/questions/1217539/net-expression-trees-tutorial
但是,如果您想要更快更脏的东西,则可以继续将这些
Where
子句链接到foreach
内:-IEnumerable<T> query = List1;
foreach (var property in IndexFields)
{
// The variable "property" gets hoisted out of local context
// which messes you up if the query is being evaluated with
// delayed execution.
// If you're working in C# 6 though, you don't need to do this.
var localProperty = property;
query = query.Where(
p => (p.GetType().GetProperty(localProperty)
.GetValue(p, null) as string) == "red");
}
var sitem = query.FirstOrDefault();
关于c# - 在多个属性上构建动态的where子句,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17106934/