2015-12-21 79 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事實上,一旦你得到它,它並不複雜。最簡單的方法是創建一些具體的表達式,例如簡化的例子,並用調試器探索它們。我也很着急並且解決了一些問題。我會用一個簡單的版本來更新答案。 –