Использование делегата для проецирования в Linq to SQL - PullRequest
9 голосов
/ 25 мая 2010

У меня есть что-то вроде этого в реализации IRepository в Linq to Sql:

var newlist = from h in list where h.StringProp1 == "1"
                      select new MyBusinessBO{
                          firstProp = h.StringProp1,
                          secondProp = h.StringProp2
                      };

Проецирование в MyBusinessBO не сложно, но когда у Business Object есть много свойств, код проекции становится очень длинным. Кроме того, поскольку проекция может происходить в нескольких местах в репозитории, мы нарушаем принцип СУХОГО.

Есть ли способ абстрагировать проекцию или заменить ее делегатом?

т.е. заменить код

                          firstProp = h.StringProp1,
                          secondProp = h.StringProp2

с чем-то многоразовым?

Ответы [ 4 ]

7 голосов
/ 25 мая 2010

Вы можете решить эту проблему, используя точечный синтаксис, а не синтаксис в стиле LINQ.

Ваш текущий:

list
    .Where(h => h.StringProp1 == "1")
    .Select(h => new MyBusinessBO
    {
        firstProp = h.StringProp1,
        secondProp = h.StringProp2
    });

Потенциальное решение:

Func<MyType, MyBusinessBO> selector = h => new MyBusinessBO
{
    firstProp = h.StringProp1,
    secondProp = h.StringProp2
};
list
    .Where(h => h.StringProp1 == "1")
    .Select(selector);

И вы могли бы где-нибудь передать селектор или сгенерировать его на лету или что-то в этом роде.

5 голосов
/ 25 мая 2010

Queryable.Select требует Expression<Func<T, U>>. Вы можете написать метод, который возвращает это, и использовать этот метод везде, где вы выполняете преобразование.

public Expression<Func<DataObj, BusiObj>> GetExpr()
{
  return h => new BusiObj()
  {
    firstProp = h.StringProp1,
    secondProp = h.StringProp2
  };
}


 //get a local variable holding the expression.
Expression<Func<DataObj, BusiObj>> toBusiObj = GetExpr();

//use it thusly
var newList = (from h in list where h.StringProp1 == "1" select h)
  .Select(toBusiObj)
  .ToList();

//or
List<BusiObj> newList = list
  .Where(h => h.StringProp1 == "1")
  .Select(toBusiObj)
  .ToList();
0 голосов
/ 25 мая 2010

Возможно, использовать обычные конструкторы не по умолчанию, а не инициализаторы объектов. Или, если вы можете начать использовать C # 4.0, попробуйте добавить в смесь необязательные параметры / параметры по умолчанию.

0 голосов
/ 25 мая 2010

Взгляните на AutoMapper и похожие инструменты

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