2015-12-21 80 views
0

假设我有以下的(用于显示在下拉列表中的项目):可重复使用的逻辑查询

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>上运行并传入“get name”函数,但我无法使它与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层。

回答

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) 
    } 
} 
+0

是的,这是真的,这是我正在考虑另一种方法(但我想,以避免它,因为我真正需要的是编号和名称) –

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(); 

} 
+0

好了,你就得到完成工作的要点 - 但目前这是复杂/脆弱性的一次巨大飞跃,这是不值得的。尽管如此。 –

+0

@MarkSowul事实上,一旦你得到它,它并不复杂。最简单的方法是创建一些具体的表达式,例如简化的例子,并用调试器探索它们。我也很着急并且解决了一些问题。我会用一个简单的版本来更新答案。 –