I'm trying to write a dynamic LINQ query using Expressions (for the first time) to achieve this:
public override IQueryable<SelectListDto> GetSelectList()
{
var ageGroups = DbContext.Set<AgeGroup>()
.Select(x => new SelectListDto() { ID = x.ID, Name = x.Description_Chinese });
return ageGroups;
}
The SelectListDto class looks like this:
public class SelectListDto : IRequestDto
{
public int ID { get; set; }
public string Name { get; set; }
}
Here's the code for my Expression, which I tried to adapt from the code give in the answer to this question:
protected Func<TEntity, SelectListDto> GetSelectListStatement()
{
var entityType = typeof(TEntity);
var entityIDProperty = entityType.GetProperty("ID");
var entityNameProperty = entityType.GetProperty(GetPropertyNameForSelectListDescription()); // Returns the name of the property on TEntity to map to SelectListDto.Name
var parameterExpression = Expression.Parameter(typeof(TEntity), "x"); // "x" in x => ..., linked to the TEntity
var newExpression = Expression.New(typeof(SelectListDto)); // "new SelectListDto()"
var idMemberExpression = Expression.Property(parameterExpression, entityIDProperty); // "x.ID"
var nameMemberExpression = Expression.Property(parameterExpression, entityNameProperty); // "x.Name"
var idBinding = Expression.Bind(entityIDProperty, idMemberExpression); // "ID = x.ID"
var nameBinding = Expression.Bind(entityNameProperty, nameMemberExpression); // "Name == x.Name"
var bindings = new List<MemberAssignment>() { idBinding, nameBinding };
var memberInitExpression = Expression.MemberInit(newExpression, bindings); // initialization "new SelectListDto { ID = x.ID, Name = x.Name }"
var lambda = Expression.Lambda<Func<TEntity, SelectListDto>>(memberInitExpression, parameterExpression); // // expression "x => new SelectListDto { ID = x.ID, Name = x.Name }"
return lambda.Compile();
}
But this code throws the Exception
"ID" is not a member of type "SelectListDto"
It seems pretty clear to me that ID is a member of SelectList. So I am stumped at this point.
EDIT:
Here's the code that worked after being guided to the solution by Asad:
protected Func<TEntity, SelectListDto> GetSelectListStatement()
{
var entityType = typeof(TEntity);
var selectListDtoType = typeof(SelectListDto);
var entityIDProperty = entityType.GetProperty("ID");
var entityNameProperty = entityType.GetProperty(GetPropertyNameForSelectListText());
var selectListDtoIDProperty = selectListDtoType.GetProperty("ID");
var selectListDtoNameProperty = selectListDtoType.GetProperty("Name");
var parameterExpression = Expression.Parameter(entityType, "x");
var newInstantiationExpression = Expression.New(selectListDtoType);
var idMemberExpression = Expression.Property(parameterExpression, entityIDProperty);
var nameMemberExpression = Expression.Property(parameterExpression, entityNameProperty);
var idBinding = Expression.Bind(selectListDtoIDProperty, idMemberExpression);
var nameBinding = Expression.Bind(selectListDtoNameProperty, nameMemberExpression);
var bindings = new List<MemberAssignment>() { idBinding, nameBinding };
var memberInitExpression = Expression.MemberInit(newInstantiationExpression, bindings);
var lambda = Expression.Lambda<Func<TEntity, SelectListDto>>(memberInitExpression, parameterExpression);
return lambda.Compile();
}