[英]Hide virtual method implementation if overloaded method is present in concrete implementation
[英]Generic virtual method and concrete Implementation?
我目前正在編寫一段代碼,其中 Generics 讓我發瘋。 也許有人可以指出這個問題。
我們所有的DatabaseEntities
都有通用接口,例如IDatabaseEntityWithId
。
假設有EntityA: IDatabaseEntityWithId
。 我們有不同的非通用 Forms / 控件。 我們也有應該共享的控件,並且獨立於具體類型來完成它們的工作。
現在,來自 Java 這在那里非常容易,因為每個控件都可以只使用例如List<?>
並傳遞/處理列表而不用真正關心里面的內容。
因此,我們的 Search-Control 也應該能夠“處理” List<T>
和IQueryable<T>
而無需關心T
實際是什么。
EntityList
的基本實現具有以下方法,我們的搜索應該利用這些方法來生成結果、進行分頁等。
public class EntityListControl{
public virtual IQueryable<T> BaseQuery<T>(DBContext dbContext) where T : IDBEntityWithId => throw new NotImplementedException();
public virtual List<string> AutocompleteSuggestionsQuickSearch() => throw new NotImplementedException();
public virtual List<IDBEntityWithId> DoQuickSearch(string reference) => throw new NotImplementedException();
public virtual IQueryable<T> DoTaggedSearchExtensions<T>(IQueryable<T> query, DbContext dbContext) where T : IDBEntityWithId => throw new NotImplementedException();
}
SearchControl
有一個對當前加載的EntityListControl
的引用,基本上應該充當具體方法的協調器,即縮短它看起來像:
class SearchControl{
public void DoSearch(){
String[] searchTags = this.SearchField.Text.Split(' ');
using (DbContext db = DbContext.Factory()){
var query = this.EntityListControl.BaseQuery<IDBEntityWithId>(db);
//do other stuff.
query = this.EntityListControl.DoTaggedSearchExtension<IDBEntityWithID>(query, db);
//do other stuff
List<IDBEntityWithId> result = query.Take(X).ToList();
//do other stuff
this.EntityListView.FactoryRows(result);
}
你會明白的。
現在,對於其中一個EntityListControl
實現,這些方法可能如下所示:
public class EntityList: UserControl{
...
}
...
public class EntityListA : EntityList{
public override IQueryable<EntityA> BaseQuery<EntityA>(DbContext db){
return db.EntityA.Include("EntityB").Include("EntityC");
}
public IQueryable<EntityA> DoTaggedSearchExtension<EntityA>(IQueryable<EntityA> query, DbContext db){
//Problem is now here...
return query.Where(x => x.PropertyOfEntityA == true);
}
}
問題現在出在DoTaggedSearchExtension
的具體實現中。 Visual Studio 在這里清楚地指出, T
是EntityA
並且查詢是IQueryable<EntityA>
- 但拒絕接受不屬於IDBEntityWithId
的任何屬性。 這是為什么?
錯誤消息甚至顯示為“EntityA 不包含‘屬性’的定義……”——這是錯誤的,它就在那里……IntelliSense 只是提出通用接口的屬性。
顯然,在通用的EntityListControl
中,我不能更具體地說明T
的類型, IBaseEntityWithId
是我可以為所有實體確保的通用接口之一。
Ofc,我可以放棄整個通用部分,只使用接口,將它們轉換為實現中的實際類型,但這不是重點,不是嗎?
關於如何修復這個特定示例的任何建議?
您希望基礎 class 是通用的,而不是方法!
public class EntityList<T> where T : IDBEntityWithId
{
public virtual IQueryable<T> BaseQuery(DBContext dbContext) => throw new NotImplementedException();
public virtual List<string> AutocompleteSuggestionsQuickSearch() => throw new NotImplementedException();
public virtual List<IDBEntityWithId> DoQuickSearch(string reference) => throw new NotImplementedException();
public virtual IQueryable<T> DoTaggedSearchExtensions(IQueryable<T> query, DbContext dbContext) => throw new NotImplementedException();
}
當你實現它時,你會得到你期望的具體類型
public class EntityListA : EntityList<EntityA>{
public override IQueryable<EntityA> BaseQuery(DbContext db){
return db.EntityA.Include("EntityB").Include("EntityC");
}
public IQueryable<EntityA> DoTaggedSearchExtension(IQueryable<EntityA> query, DbContext db){
//Problem is now here... (Not any more it isnt!)
return query.Where(x => x.PropertyOfEntityA == true);
}
}
現場演示示例: https://do.netfiddle.net/SiICNV (編譯正常但必須注釋掉特定於 EF 的內容)
DoTaggedSearchExtension 的定義標識 T 是一個 IDBEntityWithId
C# 是強類型的,所以它只允許在 IDBEntityWithId 上定義的方法
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.