簡體   English   中英

通用虛擬方法和具體實現?

[英]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 在這里清楚地指出, TEntityA並且查詢是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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM