为了账号安全,请及时绑定邮箱和手机立即绑定

C# OOP:在基础具体类中使用带有类型参数的接口

C# OOP:在基础具体类中使用带有类型参数的接口

C#
拉风的咖菲猫 2021-12-25 16:56:17
我希望标题是对问题的描述,我在表述我要解决的问题时遇到了麻烦。我正在使用 .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   }   ....}现在,我想做的很简单。我想补充的过载Create上IRepository接受一个IEnumerable的TEntity:public interface IRepository<TEntity, TPrimaryKey> where TEntity : class   ...   void Create(IEnumerable<TEntity> entities);   ...但是我想定义一次这个重载的实现:所以我想我可以制作一个抽象的基本存储库类来放置上述实现。我面临的问题是我不确定如何或者甚至我是否可以用我现在拥有的模型干净利落地做到这一点。我试图创建一个实现 的基类,但这意味着将类型参数传递给基类和接口:IRepositorypublic 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   }   ....}这对我来说并不安静,因为我在IProductRepository和中都传递了相同类型的参数ProductRepository。我觉得我很接近但不在那里,我不确定这里的最佳实践方法是什么。如果有人可以建议一种方法,我将非常感谢您的反馈。为这篇文章的长度道歉,但我觉得我需要清楚地描述我想要做什么。谢谢!
查看完整描述

2 回答

?
一只甜甜圈

TA贡献1836条经验 获得超5个赞


在接口和抽象类中具有相同的类型参数并不是什么大问题。使用您的抽象类解决方案是可以的,除非您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(...);


查看完整回答
反对 回复 2021-12-25
?
湖上湖

TA贡献2003条经验 获得超2个赞

这就是我要做的方式。我会打破之间的继承IRepository和IProductRepository:


这是您的接口:


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.


查看完整回答
反对 回复 2021-12-25
  • 2 回答
  • 0 关注
  • 186 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信