user2535425
user2535425

Reputation:

Generic order by parameter

I'm trying to do a generic method that would accept an order by parameter that I could then inspect for it's name and attributes before building the query and sending it to the database.

I was thinking of something like:

    public class SearchEngine<T>
    {
        // Removed other parameters to make it simple
        public IEnumerable<T> Search<K>(Func<T, K> orderBy)
        {
            throw new NotImplementedException();
        }
    }

I was hoping to consume it later with:

        var searchEngine = new SearchEngine<User>();

        var result = searchEngine.Search(x => x.Name);

My goal is to get a hold, inside of the search method, of that property so that I could get the name of the property, "Name" in this case, and even after it, use reflection to get its attributes to get other information I have setup.

I know about getting the attributes, what I'm not sure is how can I get the info of the property being passed. I'm sure Linq does this in some way, I just don't know how.

If I tried something like:

var result = searchEngine.Search<PropertyInfo>(x => x.Name);

This wouldnt work since the parameter is returning a string in this case.

Any ideas would be appreciated.

Upvotes: 1

Views: 155

Answers (3)

Wagner DosAnjos
Wagner DosAnjos

Reputation: 6374

You can use Dynamic Linq. The syntax would be something like:

string criteria = "Age < 40 and Age > 30";
string sort = "Name";

var result = searchEngine.Where(criteria).OrderBy(sort);

Upvotes: 0

neodim
neodim

Reputation: 487

Change parameter type of Search to:

Expression<Func<T, K>>

and try like this:

public class SearchEngine<T>
{
    // Removed other parameters to make it simple
    public IEnumerable<T> Search<K>(Expression<Func<T, K>> orderBy)
    {
        var name = GetMemberName(orderBy.Body);

        throw new NotImplementedException();
    }

    static string GetMemberName(Expression expression)
    {
        string memberName = null;

        var memberExpression = expression as MemberExpression;
        if (memberExpression != null)
            memberName = memberExpression.Member.Name;

        var unaryExpression = expression as UnaryExpression;
        if (unaryExpression != null)
            memberName = ((MemberExpression) unaryExpression.Operand).Member.Name;

        var methodCallExpression = expression as MethodCallExpression;
        if (methodCallExpression != null)
            memberName = methodCallExpression.Method.Name;

        Contract.Assume(memberName != null);

        return memberName;
    }
}

Upvotes: 0

MarcinJuraszek
MarcinJuraszek

Reputation: 125650

Use expression tree and change Search method parameter type to Expression<Func<T, K>>:

public IEnumerable<T> Search<K>(Expression<Func<T, K>> orderBy)
{
    var memberExpression = orderBy.Body as MemberExpression;
    if (memberExpression == null)
        throw new ArgumentException("orderBy");

    var member = memberExpression.Member;
    var memberName = member.Name;

    return null;
}

It will throw ArgumentException when orderBy is not simple, member expression.

You can still call the method the same way:

var result = searchEngine.Search(x => x.Name);

Upvotes: 3

Related Questions