存储库模式和问题抽象类

发布于 2024-09-11 22:07:48 字数 2271 浏览 6 评论 0原文

遇到存储库模式与抽象类的使用相结合的问题。

我有一个存储库,它实现了返回抽象类型的 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

得到 2 个编译时错误:

'System.Collections.Generic.IEnumerable' 不包含以下定义 “ToList”和最佳扩展方法 超载 “System.Linq.ParallelEnumerable.ToList(System.Linq.ParallelQuery)”有一些无效参数

并且

实例参数:无法转换自 'System.Collections.Generic.IEnumerable' 到 'System.Linq.ParallelQuery'

那么,我该如何实现这个模式呢?

我可以理解这个问题(你无法实例化抽象类型),那么枚举器(.ToList)是否尝试实例化它,因此出现错误?

如果您不明白我想做什么:

  • 我希望我的存储库返回一个抽象类型的 ICollection
  • 我希望我的服务(每种具体类型都有一个)基于该单个存储库方法返回具体类型的列表

这只是 LINQ 语法的一个例子吗?或者我的设计模式完全错误?

Come across a problem with the repository pattern combined with the use of abstract classes.

I have a repository which implements a single method returning an ICollection of an abstract type.

Here's my abstract class:

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

Here's a concrete implementation of that abstract class:

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

Here's my repository:

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 };
    }
}

All good so far.

Now the service:

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>();
   }
}

There's the problem. I'm trying to return a list of concrete types (Country) from a repository which returns an ICollection<T> of an abstract type.

Get 2 compile-time errors:

'System.Collections.Generic.IEnumerable'
does not contain a definition for
'ToList' and the best extension method
overload
'System.Linq.ParallelEnumerable.ToList(System.Linq.ParallelQuery)' has some invalid arguments

and

Instance argument: cannot convert from
'System.Collections.Generic.IEnumerable'
to
'System.Linq.ParallelQuery'

So, how can i implement this pattern?

I can kind of understand the issue (you can't instantiate an abstract type), so does the Enumerator (.ToList) attempt to instantiate this, hence the error?

In case you don't understand what im trying to do:

  • I want my repository to return an ICollection<T> of an abstract type
  • I want my services (i will have one for each concrete type) to return a List of concrete types based on that single repository method

Is this just a case of LINQ syntax? Or is my design pattern totally wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

蓝眼泪 2024-09-18 22:07:48
repository.GetAllLocations().OfType<Country>().ToList();

您甚至不需要 LocationType 枚举

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

And you don't even need the LocationType enum

妥活 2024-09-18 22:07:48

您的问题的解决方案非常简单,您需要在 LINQ 表达式中创建一个新的国家/地区:

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

我认为您错误地使用通用 ToList 方法来创建新国家/地区的列表类型,其中 T 始终从源集合中推断出来。一般来说,每当您想要将一种类型的集合转换为另一种类型的项目集合时,您可以使用Select

The solution to your problem is pretty easy, you need to create a new Country in your LINQ expression:

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

I think you were mistaking the generic ToList<T> method to being able to create a list of a new type, wheres T is always inferred from the source collection. Generally, whenever you want to convert a collection of one type to a collection of items of another type you use Select.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文