繁体   English   中英

C#OOP:在基础混凝土类中使用带有类型参数的接口

[英]C# OOP : Using interface with type parameters in base concrete class

我希望标题能说明问题,但我在尝试解决问题时会遇到麻烦。

我正在使用.NET Core 2.1

最近五年来,我在使用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
   }
   ....
}

现在,我想做的非常简单。 我想在IRepository上添加Create的重载,该重载使用TEntityIEnumerable

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

因为我在IProductRepositoryProductRepository传递相同类型的参数,所以这对我来说并不安静。 我感觉自己已经接近但不在那儿,而且我不确定这里的最佳实践方法是什么。 如果有人可以建议一种方法,我将非常感谢您的反馈。 很抱歉,这篇文章很长,但我觉得我需要清楚地描述自己想做的事情。 谢谢!

在接口和抽象类中具有相同的类型参数没什么大不了的。 除非您的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(...);

这就是我要做的方式。 我会打破IRepositoryIProductRepository之间的继承关系:

这是您的界面:

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

internal interface IProductRepository
{
    void SomeProductRepoMethod(int someParam);
}

然后,让您的基类像您一样继承IRepository

基类:

public abstract class BaseRepository<TEntity, TPrimaryKey> : 
    IRepository<TEntity, TPrimaryKey> where TEntity : class
{
    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);
        }
    }
}

然后派生基类并实现IProductRepository

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

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

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

    public override void Delete(Product entity)
    {
        // delete
    }
}

我认为您的派生类对Product存储库的特殊性是BaseRepository上的实现细节。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM