Learner
Learner

Reputation: 786

How to dynamically generate Lambda expression in c#

I would like to do the following;

    public IEnumerable<SalesRegister> GetSalesRegister()
    {
        return _client.GetAllSalesRegisters().OrderBy(x => x.CompanyName);
    }

by doing something like;

    public IEnumerable<SalesRegister> GetSalesRegister(string sortBy)
    {
        return _client.GetAllSalesRegisters().OrderBy(x => sortBy);
    }

for this I have tried the following, but didn't work

    public IEnumerable<SalesRegister> GetSalesRegister(string sortBy)
    {
        var type = typeof(SalesRegister);
        var param = Expression.Parameter(type, "x");
        var len = Expression.PropertyOrField(param, sortBy);
        return _client.GetAllSalesRegisters().OrderBy(x => len );
    }

I am not sure if I can do it in this way, can somebody help me please?

Upvotes: 0

Views: 284

Answers (1)

brainless coder
brainless coder

Reputation: 6430

Try this -

public IEnumerable<SalesRegister> GetSalesRegister(Expression<Func<SalesRegister, object>> sortByExp)
{
    return _client.GetAllSalesRegisters().OrderBy(sortByExp.Compile());
}

You can call it like this -

GetSalesRegister(x => x.CompanyName);

To pass a lambda expression you need to have the type as Expression<Func<T, TR>> where T is base class and TR is the return type of the expression

Or, if you only have the string name try building the expression like this -

public IEnumerable<SalesRegister> GetSalesRegister(string sortBy)
{
    var param = Expression.Parameter(typeof (SalesRegister), "x");
    var prop = typeof (SalesRegister).GetProperty(sortBy);
    var objectFuncType = typeof (Func<,>).MakeGenericType(typeof (SalesRegister), prop.PropertyType);
    var propExp = Expression.PropertyOrField(param, sortBy);
    var exp = Expression.Lambda(objectFuncType, propExp, param);
    var converted = Expression.Convert(exp.Body, typeof (object)); // only needed if you are passing in no referene types like int, double, etc as parameters, otherwise ignore this line and use 'exp' in place of 'converted' in the next line
    var sortByExp= Expression.Lambda<Func<SalesRegister, object>>(converted, exp.Parameters);

    return _client.GetAllSalesRegisters().OrderBy(sortByExp.Compile());
}

You can call it like this -

GetSalesRegister("CompanyName");

Upvotes: 3

Related Questions