Search code examples
c#filtersql-order-bygeneric-listgetproperty

c# orderBy type in string


I would like to do pass the filter as string parameter.

public static List<Contact> Search(string filtre){
   var contacts =  bdContext.Contact.OrderBy( e => e.[filtre]).ToList();
   return contacts;
}

Code:

var contacts = bdContext.Contact.OrderBy(e.GetType().GetProperty(filter))

Solution

  • You can use https://www.nuget.org/packages/System.Linq.Dynamic.Library or https://www.nuget.org/packages/System.Linq.Dynamic/ (they are are library to execute "dynamic" queries based on string commands. They are nearly equivalent, because one is a branch of the other).

    using System.Linq.Dynamic;
    

    and then

    var contacts = bdContext.Contact.OrderBy(filtre).ToList();
    

    Now... if you don't really want to include a new library, you can do something like:

    // We build the expression x => x.[filtre]
    var parameter = Expression.Parameter(typeof(Contact));
    var property = Expression.Property(parameter, filtre);
    var expression = Expression.Lambda(property, parameter); // Returns a Expression<Func<Contact, typeof(propertyName)>>
    
    // The "right" overload of OrderBy, in a "safe" way
    var orderby = (from x in typeof(Queryable).GetMethods(BindingFlags.Static | BindingFlags.Public)
                   where x.Name == "OrderBy" && x.IsGenericMethod
                   let genericArguments = x.GetGenericArguments()
                   let parameters = x.GetParameters()
                   where genericArguments.Length == 2 && 
                       parameters.Length == 2 &&
                       parameters[0].ParameterType == typeof(IQueryable<>).MakeGenericType(genericArguments[0]) &&
                       parameters[1].ParameterType == typeof(Expression<>).MakeGenericType(typeof(Func<,>).MakeGenericType(genericArguments))
                   select x).Single();
    
    // We build from OrderBy<,> the OrderBy<Contact, typeof(filtre)>
    orderby = orderby.MakeGenericMethod(typeof(Contact), expression.ReturnType);
    
    // We invoke OrderBy<Contact, typeof(filtre)>
    IQueryable<Contact> ordered = (IQueryable<Contact>)orderby.Invoke(null, new object[] { bdContext.Contact, expression });
    var contacts = ordered.ToList();