首页 > 解决方案 > C# OOP:在基具体类中使用带有类型参数的接口

问题描述

我希望标题是对问题的描述,我在表达我要解决的问题时遇到了麻烦。

我正在使用 .NET Core 2.1

在过去 5 年使用 Python 之后,我最近开始在 C# 商店工作,所以我的强类型 oop 有点生疏了。这是我所拥有的以及我正在尝试做的事情:

我是一个基本存储库接口,它为数据库实体定义了基本的 CRUD 功能:

public interface IRepository<TEntity, TPrimaryKey> where TEntity : class
{
   TEntity FindById(TPrimaryKey id)
   void Create(TEntity entity);
   void Delete (TEntity entity);
}

我从这个接口继承来定义我的存储库类实现的接口:

interface IProductRepository : IRepository<Product, int>
{
   void SomeProductRepoMethod(int someParam);
}

然后我在我的具体类中实现所有接口方法:

public class ProductRepository : IProductRepository
{
   public Product FindById(int id)
   {
      // lookup
   }

   public void Create(Product product)
   {
      // save 
   }

   public void SomeProductRepoMethod(int someParam)
   {
      // do product repository specific stuff
   }
   ....
}

现在,我想做的事情相当简单。我想添加一个Createon的重载,IRepository它需要一个IEnumerableof TEntity

public interface IRepository<TEntity, TPrimaryKey> where TEntity : class
   ...
   void Create(IEnumerable<TEntity> entities);
   ...

但是我想定义一次重载的实现:所以我想我可以制作一个抽象的基础存储库类来放置上述实现。我面临的问题是我不确定如何甚至是否可以使用我现在拥有的模型干净地做到这一点。我试图创建一个实现的基类,但这意味着将类型参数传递给基类并传递给接口:IRepository

public abstract class BaseRepository<TEntity, TPrimaryKey> : IRepository<TEntity, TPrimaryKey>
{
    public abstract TEntity FindById(TPrimaryKey id);

    public abstract void Create(TEntity entity);
    public abstract void Delete(TEntity entity);
    public void Create(IEnumerable<TEntity> entities)
    {
        foreach(TEntity entity in entities)
        {
            Create(entity);
        }
    }
}

然后在我的具体存储库中:

public class ProductRepository : BaseRepository<Product, int>, IProductRepository
{
   public override Product FindById(int id)
   {
      // lookup
   }

   public override void Create(Product product)
   {
      // save 
   }

   public void SomeProductRepoMethod(int someParam)
   {
      // do product repository specific stuff
   }
   ....
}

这对我来说并不安静,因为我在IProductRepositoryand中传递了相同类型的参数ProductRepository。我觉得我很接近但不在那里,我不确定这里的最佳实践方法是什么。如果有人可以提出一种方法,我将非常感谢您的反馈。为帖子的长度道歉,但我觉得我需要清楚地描述我正在尝试做的事情。谢谢!

标签: c#oop.net-core

解决方案


在接口和抽象类中具有相同的类型参数并不是什么大问题。使用您的抽象类解决方案是可以的,除非您ProductRepository需要从其他类继承。

实际上,有了你的抽象类,你的IRepository接口就不再需要存在了。只需处理一切BaseRepository

这个问题的另一个解决方案是扩展方法。在静态类中,您可以这样写:

public static void Create<TEntity, TPrimaryKey>(this IRepository<TEntity, TPrimaryKey> repo, IEnumerable<TEntity> entities) where TEntity : class {
    // do your foreach loop here
} 

IRepository现在您可以像这样在任何实例上调用此方法:

repository.Create(...);

推荐阅读