I would like to create a repository method like this:
public List<SelectListItem> AllAsSelectListItems(
Expression<Func<T, string>> valueProperty,
Expression<Func<T, string>> textProperty,
string selectedValue = "")
{
// what goes here? I am having serious trouble with this bit!
}
That will enable me to call it like this:
List<SelectListItem> selectListItems = PersonRepository.AllAsSelectListItems(
m => m.ID,
m => m.Name,
selectedIDAsString
);
And, with the selectedValue
parameter being "1", it should produce a result like this:
List<SelectListItem>(){
{Value: "1", Text: "Ted", Selected: true},
{Value: "2", Text: "Sam", Selected: false},
{Value: "3", Text: "Tracy", Selected: false}
};
I am having trouble with the generic AllAsSelectListItems()
method.
You can see my attempt so far in the code below. But it's not ideal.
I have resorted to hard-coded strings to populate SelectListItem
properties with T
properties. I think an expression tree is the solution, but I'm struggling to code it correctly.
Also, assigning the ID
property breaks it, because it's an int
not a string
.
Finally, I am also struggling to compare the selectedValue
parameter to the SelectListItem.Value
property.
Person Class
public class Person
{
public int ID {get;set;}
public string Name {get;set;}
}
Controller
public class PersonController : Controller
{
public IPersonRepository Repository {get;set;}
public PersonController(IPersonRepository repository)
{
Repository = repository;
}
public ActionResult SelectPerson(int selectedID)
{
string selectedIDAsString = selectedID.ToString();
var selectListItems = Repository.AllAsSelectListItems(
m => m.ID,
m => m.Name,
selectedIDAsString
);
return View(selectListItems);
}
}
Repository
public class PersonRepository : Repository
{
// various specialised methods
}
public class Repository<T> : IRepository<T> where T : DBEntity
{
private ApplicationDbContext db = null;
private DbSet<T> table = null;
public RepositoryBase()
{
this.db = new ApplicationDbContext();
table = db.Set<T>();
}
public RepositoryBase(ApplicationDbContext db)
{
this.db = db;
table = db.Set<T>();
}
protected virtual IQueryable<T> AllAsQueryable(
params Expression<Func<T, object>>[] includeExpressions)
{
return includeExpressions.Aggregate<Expression<Func<T, object>>, IQueryable<T>>
(table, (current, expression) => current.Include(expression));
}
public List<SelectListItem> AllAsSelectListItems(
Expression<Func<T, string>> valueProperty,
Expression<Func<T, string>> textProperty,
string selectedValue = "")
{
// temp hard coded values until we learn how to use the expression parameters properly
string valuePropertyHardCoded = "Name";
string textPropertyHardCoded = "Name";
Type currentType = typeof(T);
var itemParam = Expression.Parameter(currentType, "x");
var valueMember = Expression.PropertyOrField(itemParam, valuePropertyHardCoded);
var textMember = Expression.PropertyOrField(itemParam, textPropertyHardCoded);
var selector = Expression.MemberInit(Expression.New(typeof(SelectListItem)),
Expression.Bind(typeof(SelectListItem).GetMember("Value").Single(), valueMember),
Expression.Bind(typeof(SelectListItem).GetMember("Text").Single(), textMember)
);
var lambda = Expression.Lambda<Func<T, SelectListItem>>(
selector, itemParam);
return AllAsQueryable().Select(lambda.Compile()).ToList();
}
}