Я использую Asp.Net Core 2.0, Automapper 6.2.2
В моем проекте я хочу, чтобы AutoMapper разрешил сопоставление двух источников одному назначению (и противоположному). Пожалуйста, рассмотрите следующую модель:
class UserA {
public CustomerId {get;set;}
public CustomerName {get;set;}
}
class UserB {
public CustomerId {get;set;}
public CustomerEmail {get;set;}
}
class UserViewModel{
public Id {get;set;}
public CustomerName {get;set;}
public CustomerEmail {get;set;}
}
Мой профиль AutoMapper настроен следующим образом:
CreateMap<UserA , UserViewModel>()
.ForMember(dest => dest.Id , opt => opt.MapFrom(src => src.CustomerID))
.ForMember(dest => dest.CustomerName, opt => opt.MapFrom(src => src.CustomerName)).ReverseMap()
.ForAllOtherMembers(x => x.Ignore());
CreateMap<UserB , UserViewModel>()
.ForMember(dest => dest.Id , opt => opt.MapFrom(src => src.CustomerID))
.ForMember(dest => dest.CustomerEmail , opt => opt.MapFrom(src => src.CustomerEmail )).ReverseMap()
.ForAllOtherMembers(x => x.Ignore());
У меня есть Rest API, который предоставляет UserViewModel и должен позволять фильтровать результаты по Id, CustomerName или CustomerEmail. Потребитель API не должен знать, к какой сущности относятся CustomerName и CustomerEmail.
Я создал сервисный метод:
public override async Task<IEnumerable<UserViewModel>> GetAsync(Expression<Func<UserViewModel, bool>> filter = null, Expression<Func<IQueryable<UserViewModel>, IOrderedQueryable<UserViewModel>>> orderBy = null, string includeProperties = null, int? skip = null, int? take = null)
Теперь я хотел бы отобразить оба параметра
Expression<Func<UserViewModel, bool>> filter
Expression<Func<IQueryable<UserViewModel>, IOrderedQueryable<UserViewModel>>> orderBy
К
Expression<Func<UserA, bool>> filterA
Expression<Func<IQueryable<UserA>, IOrderedQueryable<UserA>>> orderByA
Expression<Func<UserB, bool>> filterB
Expression<Func<IQueryable<UserB>, IOrderedQueryable<UserB>>> orderByB
но отображение дает мне исключение, когда я применяю фильтр с UserEmail и хочу сопоставить с UserA. Я бы хотел, чтобы AutoMapper игнорировал все части выражения, которые игнорируются.
т.
var filterA= Mapper.Map<Expression<Func<UserA, bool>>>(filter);
дает исключение
ArgumentNullException: Value cannot be null.
Parameter name: memberInfo
AutoMapper.Internal.ReflectionHelper.GetMemberType(MemberInfo memberInfo)
AutoMapperMappingException: Error mapping types.
Mapping types:
Expression1`1 -> Expression`1
System.Linq.Expressions.Expression1`1[[System.Func`2[[Cluster.Users.ViewModel.UserDetailViewModel, Cluster.User, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[System.Boolean, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]] -> System.Linq.Expressions.Expression`1[[System.Func`2[[Cluster.Model.SimsModel.UserDetail, Cluster.Model, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[System.Boolean, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]
lambda_method(Closure , Expression1<Func<UserDetailViewModel, bool>> , Expression<Func<UserDetail, bool>> , ResolutionContext )
Последняя проблема заключается в том, что UserA и UserB хранятся в двух отдельных базах данных, поэтому они выбираются из БД с использованием двух разных контекстов БД.
Редактировать
Я также пробовал проекцию Automapper, которая, кажется, правильно выбирает данные, но отдельно извлекает все связанные коллекции (В моем вопросе я предоставил упрощенную модель, чтобы лучше объяснить проблему, но реальные сущности зависят от одного до -много отношения).
Другая проблема заключается в том, что он также немного нарушает архитектуру, так как мне бы пришлось получить GetQueryable () из репозитория и построить запрос в сервисе вместо прямой передачи всех параметров в репозиторий.
var usersA = _readOnlyRepository.GetQueryable<UserA>().ProjectTo<UserViewModel>().Where(filter).ToList();
var usersB = _readOnlyRepository.GetQueryable<UserB>().ProjectTo<UserViewModel>().Where(filter).ToList();