2014-02-10 4 views
1

Я пытаюсь сделать общий метод, который будет принимать порядок по параметру, который я мог бы затем проверить для его имени и атрибутов, прежде чем строить запрос и отправлять его в базу данных.Общий порядок по параметру

Я думал что-то вроде:

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); 

Моя цель состоит в том, чтобы ухватить, внутри метода поиска, в этом чтобы я мог получить имя свойства, «Имя» в этом случае и даже после него, использовать отражение, чтобы получить его атрибуты для получения другой информации, которую я установил.

Я знаю о получении атрибутов, что я не уверен, как я могу получить информацию о передаваемом объекте. Я уверен, что Linq делает это в некотором роде, я просто не знаю, как это сделать.

Если бы я попытался что-то вроде:

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

Это не работал бы, так как параметр возвращает строку, в данном случае.

Любые идеи будут оценены.

ответ

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); 
+0

Marcin, только что проверил это на Linqpad, и он работает точно так, как я хотел. Я понимаю ваш комментарий относительно причины возникновения аргумента, поэтому вы делаете нулевую проверку после AS. Есть ли способ ограничить их только свойствами, возможно, с помощью ограничения? –

+0

@ Революции, которые вы имеете в виду, скомпилировать ограничение времени? Или время выполнения? Во время компиляции это невозможно, чтобы проверить на runtime справку 'if' выражение:' if (memberExpression == null || memberExpression.Member.MemberType! = System.Reflection.MemberTypes.Property) '. – MarcinJuraszek

+0

время компиляции, например, где K: «что-то» –

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; 
    } 
} 
0

Вы можете использовать Dynamic Linq. Синтаксис будет примерно таким:

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

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

Спасибо, хотя я надеялся на строго типизированный подход к этому. –

Смежные вопросы