我正在尝试做一个接受按参数排序的通用方法,然后我可以在构建查询并将其发送到数据库之前检查它的名称和属性。
我想的是:
public class SearchEngine<T>
{
// Removed other parameters to make it simple
public IEnumerable<T> Search<K>(Func<T, K> orderBy)
{
throw new NotImplementedException();
}
}
我希望以后能用它来消费:
var searchEngine = new SearchEngine<User>();
var result = searchEngine.Search(x => x.Name);
我的目标是在搜索方法内部保留该属性,以便我可以获取属性的名称,在这种情况下为“Name”,甚至在它之后,使用反射来获取其属性获取我已设置的其他信息。
我知道获取属性,我不确定的是如何获取传递的属性的信息。我确信Linq以某种方式做到这一点,我只是不知道如何。
如果我尝试过类似的事情:
var result = searchEngine.Search<PropertyInfo>(x => x.Name);
这不起作用,因为在这种情况下参数返回一个字符串。
任何想法都会受到赞赏。
答案 0 :(得分:3)
使用expression tree并将Search
方法参数类型更改为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;
}
当ArgumentException
不简单时,它会抛出orderBy
,成员表达式。
您仍然可以采用相同的方式调用该方法:
var result = searchEngine.Search(x => x.Name);
答案 1 :(得分:0)
将搜索的参数类型更改为:
Expression<Func<T, K>>
并尝试这样:
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;
}
}
答案 2 :(得分:0)
您可以使用Dynamic Linq。语法如下:
string criteria = "Age < 40 and Age > 30";
string sort = "Name";
var result = searchEngine.Where(criteria).OrderBy(sort);