0

right now I'm doing something like this:

if (name == "Person")
{
    query = query.Where(o => o.Person == val);
}
else if (name == "Location")
{
    query = query.Where(o => o.Location == val);
}
else if (name == "Date")
{
    query = query.Where(o => o.Date == val);
}
...

I would like to be able to do something like this:

   query = WhereEquals(query, name, val);
buga
  • 852
  • 9
  • 21
  • 2
    Hi @buga, welcome to Stack Overflow. [DynamicLinq](https://dynamic-linq.net/) may meet your requirement. – Yong Shun May 09 '21 at 10:00
  • Your approach is much better than reflection if you just have few fix properties. @YongShun: Costs how much(in $ and performance)? – Tim Schmelter May 09 '21 at 10:05
  • think EF won't be able to use this lambda to transform it into sql if I use reflection – buga May 09 '21 at 10:09
  • 2
    @buga [Get property value from string using reflection](https://stackoverflow.com/questions/1196991/get-property-value-from-string-using-reflection) & [How to get a property value using reflection](https://stackoverflow.com/questions/10338018/how-to-get-a-property-value-using-reflection) & [How to get a property value based on the name](https://stackoverflow.com/questions/5508050/how-to-get-a-property-value-based-on-the-name) & [C# Reflection get Field or Property by Name](https://stackoverflow.com/questions/16305529/c-sharp-reflection-get-field-or-property-by-name) –  May 09 '21 at 10:17

2 Answers2

0

i dont have an answer for where method. but there is one extension method you can use to achive your goal. this method uses like function if u want exact match just remove '%' sign from searchTerm

        public static IQueryable<T> Search<T>(this IQueryable<T> source, string propertyName, string searchTerm)
    {
        if (string.IsNullOrEmpty(propertyName) || string.IsNullOrEmpty(searchTerm))
        {
            return source;
        }

        var property = typeof(T).GetProperty(propertyName);

        if (property is null)
        {
            return source;
        }

        searchTerm = "%" + searchTerm + "%";
        var itemParameter = Parameter(typeof(T), "item");

        var functions = Property(null, typeof(EF).GetProperty(nameof(EF.Functions)));
        var like = typeof(DbFunctionsExtensions).GetMethod(nameof(DbFunctionsExtensions.Like), new Type[] { functions.Type, typeof(string), typeof(string) });

        Expression expressionProperty = Property(itemParameter, property.Name);

        if (property.PropertyType != typeof(string))
        {
            expressionProperty = Call(expressionProperty, typeof(object).GetMethod(nameof(object.ToString), new Type[0]));
        }

        var selector = Call(
                   null,
                   like,
                   functions,
                   expressionProperty,
                  Constant(searchTerm));

        return source.Where(Lambda<Func<T, bool>>(selector, itemParameter));
    }
0

From your exepmle this will work supposing the value is passed with the right type:

    private Func<T, bool> WhereEquals<T>(string propertyName, object value)
    {
        return obj => typeof(T).GetProperty(propertyName)?.GetValue(obj)?.Equals(value) ?? false;
    }

    var activePeople = list.Where(WhereEquals<Person>("IsActive", true));

Or:

    private bool WhereEquals<T>(T obj, string propertyName, object value)
    {
        return typeof(T).GetProperty(propertyName)?.GetValue(obj)?.Equals(value) ?? false;
    }


    var activePeople = list.Where(obj => WhereEquals(obj, nameof(obj.IsActive), true));

If I did understand your question correctly.

Ben
  • 1
  • 2