假设我有以下内容(用于在下拉列表中显示项目):
class SelectItemViewModel<TId>
{
string Name {get; set;}
TId Id {get; set;}
}
以及我的数据库实体:
interface IEntity<TId>
{
TId Id {get;
}
我希望能够重用逻辑来创建这些下拉项,并传递一些名称。例如,我现在(简化):
List<SelectItemViewModel<int>> GetAvailableEntity1Items(IQuerable<Entity1> entities)
{
return entities
.Select(e => new SelectItemViewModel<int>
{
Id = e.Id,
Name = e.Title
})
.ToList();
}
List<SelectItemViewModel<short>> GetAvailableEntity2Items(IQuerable<Entity2> entities)
{
return entities
.Select(e => new SelectItemViewModel<short>
{
Id = e.Id,
Name = e.Description
})
.ToList();
}
他们显然具有相同的基本结构。我想对IEntity<T>
进行操作并传入“获取名称”功能,但我无法使用Entity Framework。
不起作用:
List<SelectItemViewModel<TId> GetAvailableItems<TEntity, TId>(IQueryable<TEntity> entitiesQuery, Func<TEntity, string> getNameForEntity)
where TEntity : class, IEntity<TId>
{
return entitiesQuery
.Select(e => new SelectItemViewModel<TId>
{
Id = e.Id,
Name = getNameForEntity(e)
}
}
我无法弄清楚我是如何实施的
List<SelectItemViewModel<TId> GetAvailableItems<TEntity, TId>(IQueryable<TEntity> entitiesQuery, Expression<Func<TEntity, string>> getNameForEntity)
where TEntity : class, IEntity<TId>
{
return entitiesQuery
.Select(e => new SelectItemViewModel<TId>
{
Id = e.Id,
Name = ??
}
}
有没有办法在这里重用逻辑?我能想到的另一件事是另一个界面,例如IHasName
获取名称,但坦率地说,我不希望数据库实体负责指明它们应如何在UI层中显示。
答案 0 :(得分:1)
另一种方法是从数据库中检索整个实体,然后将其转换为SelectItemViewModel:
List<SelectItemViewModel<TId> GetAvailableItems<TEntity, TId>(IQueryable<TEntity> entitiesQuery, Func<TEntity, string> getNameForEntity)
where TEntity : class, IEntity<TId>
{
return entitiesQuery
.AsEnumerable()
.Select(e => new SelectItemViewModel<TId>
{
Id = e.Id,
Name = getNameForEntity(e)
}
}
答案 1 :(得分:1)
我无法弄清楚我是如何实施的
欢迎来到System.Linq.Expressions
。像这样的事情应该做的工作
List<SelectItemViewModel<TId>> GetAvailableItems<TEntity, TId>(IQueryable<TEntity> source, Expression<Func<TEntity, string>> nameSelector)
where TEntity : class, IEntity<TId>
{
var item = nameSelector.Parameters[0];
var targetType = typeof(SelectItemViewModel<TId>);
var selector = Expression.Lambda<Func<TEntity, SelectItemViewModel<TId>>>(
Expression.MemberInit(Expression.New(targetType),
Expression.Bind(targetType.GetProperty("Name"), nameSelector.Body),
Expression.Bind(targetType.GetProperty("Id"), Expression.Property(item, "Id"))
), item);
return source.Select(selector).ToList();
}