LINQ, где условие с динамическим столбцом - PullRequest
0 голосов
/ 24 октября 2018

У меня есть этот код

// IQueryable<General> query

if (columnName == "Column1") 
{
  query = query.Where(x => x.Column1 == searchValue);
}
else if (columnName == "Column2") 
{
  query = query.Where(x => x.Column2 == searchValue);
}
else if (columnName == "Column3") 
{
  query = query.Where(x => x.Column3 == searchValue);
}
else if (columnName == "Column4") 
{
  query = query.Where(x => x.Column4 == searchValue);
}
// next zilions columns to come
// ...

и мой вопрос.Как я могу передать x.Column в качестве параметра внутри условия ".Where"?

Ответы [ 3 ]

0 голосов
/ 24 октября 2018

Вы можете использовать отражение и методы расширения.В качестве грубого примера:

public class Foo
{
  public int Column1 { get; set; }
  public int Column2 { get; set; }
  ...
}

public static class FooExtensions
{
  // I would use the actual type here instead of object if you know the type.
  public static object GetProperyValue(this Foo foo, string columnName)
  {
    var propertyInfo = foo.GetType().GetProperty(columnName);
    var value = propertyInfo.GetValue(foo);
    // as well as cast value to the type
    return value;
  }
}

...

query = query.Where(x => x.GetProperyValue(columnName) == searchValue);
...

В качестве примечания: это не очень хорошо продуманный запрос, потому что каждый раз, когда вы добавляете столбец в вашу модель, вам необходимо обновить if - else.Это нарушает O в SOLID .

0 голосов
/ 24 октября 2018

Вы можете создать предикат вручную.Используйте этот метод:

public static Expression<Func<General, bool>> CreatePredicate(string columnName, object searchValue)
{
    var xType = typeof(General);
    var x = Expression.Parameter(xType, "x");
    var column = xType.GetProperties().FirstOrDefault(p => p.Name == columnName);

    var body = column == null
        ? (Expression) Expression.Constant(true)
        : Expression.Equal(
            Expression.PropertyOrField(x, columnName),
            Expression.Constant(searchValue));

    return Expression.Lambda<Func<General, bool>>(body, x);
}

Теперь вы можете применить свой предикат:

IQueryable<General> query = //
var predicate = CreatePredicate(columnName , searchValue);
query = query.Where(predicate);
0 голосов
/ 24 октября 2018

Вы можете использовать Reflection для получения свойства по имени

x.GetType().GetProperty(propertyName,BindingFlags).SetValue(x,value)
// propertyName = "Column1" for example
// BindingFlags are most likely Instance, Public and Property (IIRC)

или передать PropertyInfo непосредственно в метод в качестве параметра.Ваш выбор зависит от уровня абстракции, который вы хотите показать потребителям вашего метода.

...