Entity Framework универсальный - PullRequest
5 голосов
/ 31 марта 2012

У меня есть такой код:

switch(sort.Column)
{
  case "code":
    model = (sort.Direction == SortDirection.Ascending)
            ? model.OrderBy(x => x.code)
            : model.OrderByDescending(x => x.code);
    break;
  case "name":
    model = (sort.Direction == SortDirection.Ascending)
            ? model.OrderBy(x => x.name)
            : model.OrderByDescending(x => x.name);
    break;
..............
}

У меня есть около 10-15 полей (например, «код» и «имя»), и я не хочу копировать и вставлять аналогичный код только с одним отличием - именем поля.

Есть ли способ как-то обобщить запрос?

Ответы [ 3 ]

7 голосов
/ 31 марта 2012

Вы можете использовать отражение (предполагается, что code и name являются свойствами; если они являются общедоступными переменными, вам придется соответственно изменить):

model = (sort.Direction == SortDirection.Ascending)
  ? model.OrderBy( x => x.GetType()
      .GetProperty( sort.Column ).GetValue( x, null ) ) :
  : model.OrderByDescending( x => x.GetType()
      .GetProperty( sort.Column ).GetValue( x, null ) );

Как указывает Дунк в комментариях ниже, этот подход заставляет размышлять на каждом шаге перечисления, и размышление обходится дорого по мере выполнения операций. Если ваша коллекция однородна, вы можете добиться лучшей производительности, переместив отражение из перечисления. Если ваш model содержит только элементов типа Foo, вы можете сделать следующее:

var prop = typeof( Foo ).GetProperty( sort.Column );

model = (sort.Direction == SortDirection.Ascending)
  ? model.OrderBy( x => prop.GetValue( x, null ) ) :
  : model.OrderByDescending( x => prop.GetValue( x, null ) );

Обратите внимание, что это приведет к TargetException, если ваша коллекция не однородна.

3 голосов
/ 31 марта 2012

Это поможет вам начать, но вы также можете использовать отражение, чтобы получить имя свойства через столбец, если свойство и столбец точно совпадают.

// inline function
Func<Func<Model, TResult>, Model> Order = criteria => 
{
    return (sort.Direction == SortDirection.Ascending)
            ? model.OrderBy(criteria)
            : model.OrderByDescending(criteria);
}

... code down to switch ...

Это приведет к сокращению вашего имени до:

model = Order(x => x.name);

Но с отражением вы могли бы сделать это без переключателя, но я немного слаб в отражении, поэтому я оставлю это кому-то другому, если они захотят.

1 голос
/ 31 марта 2012

Как говорит «Нет таких IP», для этого есть шаблоны - диспетчер команд / метод фабрики / и т.д.Это действительный выбор.Но иногда они могут просто скрыть сложность.Я предлагаю посмотреть на использование динамического linq.Вот ссылка, с которой можно начать: http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

Вы также можете бросить свой собственный, если хотите, так как это не слишком сложно.Создайте свои собственные методы расширения, которые позволят вам передавать параметры (например, направление сортировки, столбец сортировки) о вашем заказе, а в этом методе расширения создавать свой собственный заказ с помощью оператора, используя пространство имен system.linq.expressions.Вот пример этого также: http://ronniediaz.com/2011/05/24/orderby-string-in-linq-c-net-dynamic-sorting-of-anonymous-types/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...