簡體   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