2010-07-30 87 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