我所拥有的是一个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/

10-17 00:12