Я имею, кодируют что-то вроде этого в реализации IRepository в Linq к Sql:
var newlist = from h in list where h.StringProp1 == "1"
select new MyBusinessBO{
firstProp = h.StringProp1,
secondProp = h.StringProp2
};
Проекция в MyBusinessBO не является difificult, но когда Бизнес-объект имеет много свойств, код проекции становится очень длинным. Кроме того, поскольку проекция может произойти в нескольких местах в Репозитории, мы повреждаем принцип DRY.
Там какой-либо путь состоит в том, чтобы абстрагировать проекцию или заменить ее делегатом?
Т.е. замените код
firstProp = h.StringProp1,
secondProp = h.StringProp2
с чем-то допускающим повторное использование?
Queryable.Select
требует Expression
. Вы можете написать метод, который возвращает это значение, и использовать этот метод везде, где вы выполняете преобразование.
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();
Возможно, используйте обычные недефолтные конструкторы, а не инициализаторы объектов. Или, если вы можете начать использовать C# 4.0, попробуйте добавить опциональные/дефолтные параметры.
Эту проблему можно решить, используя синтаксис с точкой, а не синтаксис в стиле 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);
И вы можете передать селектор где-нибудь или сгенерировать его на лету или что-то в этом роде.