2010-07-30 83 views
3

遇到存儲庫模式與使用抽象類相結合的問題。存儲庫模式和抽象類的問題

我有一個存儲庫,它實現了一個方法返回一個抽象類型的ICollection。

這裏是我的抽象類:

public abstract class Location 
{ 
    public abstract string Name { get; set; } 
    public abstract LocationType Type { get; } 
} 

這裏有一個具體實現該抽象類:

public class Country : Location 
{ 
    public override string Name { get; set; } 
    public override LocationType Type { get { return LocationType.Country; } } 
} 

這裏是我的

public class LocationsRepository : Locations.Repository.ILocationsRepository 
{ 
    public ICollection<Location> GetAllLocations() 
    { 
     Country america = new Country { Name = "United States" }; 
     Country australia = new Country { Name = "Australia" }; 
     State california = new State { Name = "California", Country = america }; 

     return new List<Location>() { america, australia, california }; 
    } 
} 

目前爲止都是很好的。

現在服務

public class CountryService : ICountryService 
{ 
    private ILocationsRepository repository; 

    public CountryService() 
    { 
     // in reality this is done by DI, but made 'greedy' for simplicity. 
     this.repository = new LocationsRepository(); 
    } 

    public List<Country> GetAllCountries() 
    { 
     // errors thrown by compiler 
     return repository.GetAllLocations() 
         .Where(l => l.Type == LocationType.Country) 
         .ToList<Country>(); 
    } 
} 

有問題。我試圖從存儲庫中返回一個具體類型列表(Country),該存儲庫返回一個抽象類型的ICollection<T>

獲得2編譯時錯誤:

'System.Collections.Generic.IEnumerable' 不包含 'ToList' 和最佳擴展方法重載 「System.Linq的定義。 ParallelEnumerable.ToList(System.Linq.ParallelQuery)」有一些無效參數

實例參數:無法從 轉換 'System.Collections.Generic.IEnumerable' 到 'System.Linq.ParallelQuery'

那麼,如何才能實現我這個模式?

我可以理解這個問題(你不能實例化一個抽象類型),Enumerator(.ToList)也嘗試實例化這個錯誤?

如果您有什麼不明白我嘗試做的事:

  • 我想我的倉庫返回一個抽象類型
  • 我希望我的服務的ICollection<T>(我將有一個對每個具體類型)返回基於該單一存儲庫方法的具體類型列表

這只是LINQ語法的一種情況嗎?或者是我的設計模式完全錯誤?

回答

7
repository.GetAllLocations().OfType<Country>().ToList(); 

而且你甚至都不需要LocationType枚舉

+1

+1這完全是最好的解決方案。 – 2010-07-30 03:55:17

+1

太棒了,所以這是一個LINQ問題,而不是抽象/存儲庫問題。謝謝!! – RPM1984 2010-07-30 04:04:00

2

你的問題的解決方案是很容易的,你需要在你的LINQ表達式來創建一個新的國家:

return repository.GetAllLocations() 
    .Where(l => l.Type == LocationType.Country) 
    .Select(l => l as Country).ToList(); 

我認爲你是錯把通用ToList<T>方法能夠創建一個列表新類型,Wheels T總是從源集合推斷出來。通常,只要您想將一種類型的集合轉換爲另一種類型的集合,就可以使用Select

+0

我相信伊戈爾是正確的 - 它轉換爲一個新的元素選擇子句。我一直在我的回購站裏這樣做,我將Linq-to-Sql實體映射到我的域實體,並且這個內聯的Select()看起來很準確。 +1我也使用內部屬性setter/gettings,允許我將內部設置給域Entity,它使用邏輯使額外的成員可公開訪問。 – eduncan911 2010-07-30 03:46:33

+0

這也適用 - 但我傾向於@Necros的答案,因爲,少...代碼更好(它不依賴於枚舉) 任何人都可以想象這個答案和@Necros答案之間的任何區別? – RPM1984 2010-07-30 04:04:37