[英]Interface returning derived types
class Result
{
public string Data { get; set; }
}
interface IRepository
{
Result[] Search(string data);
}
我有一個相當通用的接口,它搜索“某物”並返回Result
。 IRepository
接口可以由幾個類實現,每個類都返回帶有自己唯一的元數據的自己的Result。 例如,我可以擁有一個DiskRepository
來搜索磁盤上的數據:
class DiskResult : Result
{
public int FileSize { get; set; }
public DateTime LastModifiedDate { get; set; }
}
class DiskRepository : IRepository
{
public Result[] Search(string data)
{
// ...
DiskResult[] results = GetDataFromSomewhere();
return results;
}
}
DiskResult
包含有關特定於DiskRespository
的結果的DiskRespository
。 如果我創建了另一個實現IRepository
類,則該特定實現可能具有該類獨特的元數據集。
最后,我希望搜索控制器如下所示:
class SearchController
{
private IRepository[] _repositories;
public SearchController(IRepository[] repositories)
{
_repositories = repositories;
}
public void Display(string data)
{
Result[] results = _repositories.Search(data);
// Display results
}
}
我可以輕松地在Result
類上顯示Data
屬性,但是是否有一種很好的模式來顯示從Result
派生的每個類的元數據? 我可以有一堆if
語句來檢查類是否為類型,但這感覺有些笨拙。 有沒有更好的方法來完成我要達到的目標?
其中一條評論正確指出,將虛擬Display()添加到Result類中是違反單一職責原則的。 完全正確。
這是您的問題的答案:因為您想做這樣的事情:
private IRepository[] _repositories;
...無法避免在運行時進行類型檢查。 編譯器不知道將返回哪個子類type-from-from-Result。 所有它知道您的存儲庫都返回一個Result派生對象。
另一方面,如果您使用泛型:
interface IRepository<T> where T : Result
{
T[] Search(string data);
}
...您將在編譯時知道您要處理的Result的子類類型,從而避免了類型檢查的需要,以及從第一種方法開始的長串“ if”語句。
如果您可以堅持使用泛型,那么可以執行以下操作:
interface IResultDisplayService<T> where T : Result
{
void Display(T result);
}
因此,我想我的問題是:是否必須存儲這些存儲庫的數組? 有哪些現實世界的使用場景?
我不會為此使用存儲庫接口,而是創建一個新接口:
public interface ISearchProvider
{
IEnumerable<SearchResultItem> Search(string keyword);
}
public interface ISearchResultItem
{
string Title {get; }
string Description {get; }
NameValueCollection Metadata {get; }
}
標題和描述應足以滿足90%的搜索用例。 例如, DiskResult
可能在Description
屬性中包含文件夾等。 元數據可以顯示在工具提示或詳細信息視圖中。
如果那還不夠,我也會創建一個渲染界面:
public interface ISearchResultRenderer
{
bool IsValidFor(Type type);
void Render(Stream stream);
}
並具有一個DiskResultHtmlRenderer
實現,該實現將遍歷元數據並正確地對其進行結構化。
您可以將IRepository
通用接口,例如:
interface IRepository<T>
{
T[] Search(string data);
}
您可以在結果類中有一個virtual
方法來顯示結果。 您的子類可以override
它,並可以給出自己的實現。 這樣做時,當您調用Display
方法時,您的Result
對象將調用相應的方法進行顯示。
像這樣
class Result
{
public virtual void Display()
{
//Your Code
}
//Your Code
}
class DiskResult : Result
{
public override void Display()
{
//Your Code
}
//Your Code
}
您的Display
方式
public void Display(string data)
{
Result[] results = _repositories.Search(data);
// Display results
foreach(var result in results)
{
result.Display();
}
}
希望這對您有所幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.