Reputation:
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
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
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
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