public class TestExpressionMapper
{
private static IMapper _mapper;
static void Main()
{
#region Populate test
List<EmployeeEntity> empEntity = new List<EmployeeEntity>
{
new EmployeeEntity { Id = 1, Name = "Jean-Louis", Age = 39, Events = new EventEntity[]{ new EventEntity { EventType = "Start", EventDate = DateTime.Today.AddYears(-1) } }.ToList() },
new EmployeeEntity { Id = 2, Name = "Jean-Paul", Age = 32, Events = new EventEntity[]{ new EventEntity { EventType = "Start", EventDate = DateTime.Today.AddYears(-2) } }.ToList() },
new EmployeeEntity { Id = 3, Name = "Jean-Christophe", Age = 19, Events = new EventEntity[]{ new EventEntity { EventType = "Start", EventDate = DateTime.Today.AddYears(-1) } }.ToList() },
new EmployeeEntity { Id = 4, Name = "Jean-Marie", Age = 27, Events = new EventEntity[]{ new EventEntity { EventType = "Start", EventDate = DateTime.Today.AddYears(-3) } }.ToList() },
new EmployeeEntity { Id = 5, Name = "Jean-Marc", Age = 22, Events = new EventEntity[]{ new EventEntity { EventType = "Start", EventDate = DateTime.Today.AddYears(-5) } }.ToList() },
new EmployeeEntity { Id = 5, Name = "Jean-Pierre", Age = 22, Events = new EventEntity[]{ new EventEntity { EventType = "Start", EventDate = DateTime.Today.AddYears(-5) } }.ToList() },
new EmployeeEntity { Id = 6, Name = "Christophe", Age = 55, Events = new EventEntity[]{ new EventEntity { EventType = "Start", EventDate = DateTime.Today.AddYears(-1) } }.ToList() },
new EmployeeEntity { Id = 7, Name = "Marc", Age = 23, Events = new EventEntity[]{ new EventEntity { EventType = "Start", EventDate = DateTime.Today.AddYears(-2) } }.ToList() },
new EmployeeEntity { Id = 8, Name = "Paul", Age = 38, Events = new EventEntity[]{ new EventEntity { EventType = "Start", EventDate = DateTime.Today.AddYears(-10) }, new EventEntity { EventType = "Stop", EventDate = DateTime.Today.AddYears(-1) } }.ToList() },
new EmployeeEntity { Id = 9, Name = "Jean", Age = 32, Events = new EventEntity[]{ new EventEntity { EventType = "Start", EventDate = DateTime.Today.AddYears(-10) }, new EventEntity { EventType = "Stop", EventDate = DateTime.Today.AddYears(-2) } }.ToList() },
};
#endregion
#region Mapping config
_mapper = new MapperConfiguration(cfg =>
{
cfg.CreateMap<EmployeeModel, EmployeeEntity>().ReverseMap();
cfg.CreateMap<EventModel, EventEntity>().ReverseMap();
}).CreateMapper();
_mapper.ConfigurationProvider.AssertConfigurationIsValid();
#endregion
#region Test
Expression<Func<EmployeeModel, bool>> filter;
Expression<Func<EmployeeEntity, bool>> mappedFilter;
// Works : Returns employees whose name starts with "Jean"
filter = emp => emp.Name.StartsWith("Jean");
mappedFilter = _mapper.MapExpression<Expression<Func<EmployeeEntity, bool>>>(filter);
var res1 = empEntity.AsQueryable().Where(mappedFilter);
//Works : Returns employees having at least one "Stop" event
filter = emp => emp.Events.Any(evt => evt.EventType.Equals("Stop"));
mappedFilter = _mapper.MapExpression<Expression<Func<EmployeeEntity, bool>>>(filter);
var res2 = empEntity.AsQueryable().Where(mappedFilter);
//Works : Returns employees having any event older than 3 years
filter = emp => emp.Events.Any(evt => evt.EventDate < DateTime.Today.AddYears(-3));
mappedFilter = _mapper.MapExpression<Expression<Func<EmployeeEntity, bool>>>(filter);
var res3 = empEntity.AsQueryable().Where(mappedFilter);
//Works : Returns employees having a stop event older than 1 year (no expression mapping -> lambda is built against entities)
mappedFilter = emp =>
emp.Events.Any(e => e.EventType.Equals("Stop")) &&
emp.Events.First(e => e.EventType.Equals("Stop")).EventDate < DateTime.Today.AddYears(-1);
var res4 = empEntity.AsQueryable().Where(mappedFilter);
//Breaks on mapping : Same lambda as previous one but built against models then mapped
filter = emp =>
emp.Events.Any(e => e.EventType.Equals("Stop")) &&
emp.Events.First(e => e.EventType.Equals("Stop")).EventDate < DateTime.Today.AddYears(-1);
mappedFilter = _mapper.MapExpression<Expression<Func<EmployeeEntity, bool>>>(filter);
var res5 = empEntity.AsQueryable().Where(mappedFilter);
#endregion
Console.ReadKey();
}
}
internal class EmployeeEntity
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public List<EventEntity> Events { get; set; }
}
internal class EventEntity
{
public string EventType { get; set; }
public DateTime EventDate { get; set; }
}
internal class EmployeeModel
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public List<EventModel> Events { get; set; }
}
internal class EventModel
{
public string EventType { get; set; }
public DateTime EventDate { get; set; }
}