У меня есть уровень репозитория, который имеет дело с автоматически сгенерированными объектами LINQ to SQL. В конечном итоге они преобразуются в удобные для домена типы на поверхности. Теперь я хотел бы предоставить более сложные возможности запросов для клиентского кода, и этот клиентский код знает только о типах объектов предметной области.
Я хотел бы реализовать это с помощью шаблона Query Object (как он назван в «Шаблонах архитектуры корпоративных приложений» Мартина Фаулера), но позволяя клиентскому коду использовать лямбда-выражения с типами домена. Под прикрытием я хотел бы преобразовать лямбда-выражение с поддержкой домена в лямбда-выражение с поддержкой базы данных и отправить это преобразованное выражение в репозиторий для выполнения в базе данных с помощью LINQ to SQL.
В настоящее время у меня есть реализация бедняка, которая ограничивает способность клиента отображать простые свойства, но я хотел бы немного открыть ее для более сложных запросов. Я не уверен, как бы я подошел к этому с помощью AutoMapper или любого другого существующего картографического инструмента, и я не уверен, как я могу сделать это с помощью собственного кода.
Вот какой функционал мне нужен:
// Example types to be interconverted...
// DomainId should map to DataEntityId and vice versa
// DomainName should map to DataEntityName and vice versa
public class DomainType
{
public int DomainId { get; set; }
public string DomainName { get; set; }
}
public class DataEntityType
{
public int DataEntityId { get; set; }
public string DataEntityName { get; set; }
}
// And this basic framework for a query object.
public class Query<T>
{
public Query(Func<T, bool> expression) { ... }
public Func<T, bool> Query { get; }
}
// And a mapper with knowledge about the interconverted query types
public class QueryMapper<TSource, TDestination>
{
public void SupplySomeMappingInstructions(
Func<TSource, object> source, Func<TDestination, object> dest);
public Query<TDestination> Map(Query<TSource> query);
}
// And a repository that receives query objects
public class Repository<T>
{
public IQueryable<T> GetForQuery(Query<T> query) { ... }
}
С конечной целью заставить что-то вроде этого работать:
// a repository that is tied to the LINQ-to-SQL types.
var repository = new Repository<DataEntityType>(...);
// a query object that describes which domain objects it wants to retrieve
var domain_query = new Query<DomainType>(item => item.DomainId == 1);
// some mapping component that knows how to interconvert query types
var query_mapper = new QueryMapper<DomainType, DataEntityType>();
query_mapper.SupplySomeMappingInstructions(
domain => domain.DomainId, data => data.DataEntityId);
query_mapper.SupplySomeMappingInstructions(
domain => domain.DomainName, data => data.DataEntityName);
IQueryable<DataEntityType> results =
repository.GetForQuery(query_mapper.Map(domain_query));
Мои вопросы на самом деле таковы, я думаю:
- Возможно ли создать такой маппер, и если да...
- Возможно ли это сделать с помощью такого инструмента, как AutoMapper, и если да...
- Можно ли воспользоваться преимуществами сопоставления AutoMapper, которое у меня уже есть, которое взаимопреобразовывает
DomainType
иDataEntityType
, или мне нужно явно сопоставитьQuery<DomainType>
сQuery<DataEntityType>
?
В конечном итоге я хочу сделать это, чтобы иметь возможность использовать произвольные функции отображения, которые не обязательно являются простыми свойствами объекта.