注入通用接口

时间:2015-07-07 14:40:20

标签: c# generics interface decoupling

好吧我在C#中的泛型很少迷失

我有这个通用界面

interface IInvoiceStorage<T>
    where T : class
{
    void Persist(T Invoice);
}

有两个实现接口的类

public class FacturaStorageForSQLServer:IInvoiceStorage<EVT>
{
      public void Persist(EVT Invoice)
      {
        /*Implementation*/
      }
}



public class FacturaStorageForMySQLServer:IInvoiceStorage<EVTFruit>
{
      public void Persist(EVTFruit Invoice)
      {
         /*Implementation*/
      }
}

当我想在我的服务类

中声明这个问题时,问题出现了
public class invoice_service
{
   IInvoiceStorage Storage;
   public invoice_service(IInvoiceStorage storage)
   {
     Storage=_storage;
   }
}

C#告诉我,我必须声明接口的类型,但如果我这样做,那么我的服务类将依赖于实现,而不是来自接口。

建议??

更新1: 对不起如果我声明接口将仅依赖于使用该类型的实现的类型,但如果我有两个不同类型的实现,例如EVT和EVTFruit会发生什么。

我正在考虑使用另一个界面来建立EVT和EVTFruit之间的关系,但它们可能是两个完全不同的对象,所以我不确定这是不是一个好主意。

3 个答案:

答案 0 :(得分:3)

你可以稍微改变你的课程:

public class invoice_service<T> where T : class
{
   IInvoiceStorage<T> Storage;
   public invoice_service(IInvoiceStorage<T> storage)
   {
     Storage=_storage;
   }
}

这将允许您正确使用界面并保持通用。

答案 1 :(得分:2)

根据您的需要,您还可以定义该接口的非通用版本:

public interface IInvoiceStorage
{
  ...
}

并使类继承自此接口。

public class FacturaStorageForSQLServer : IInvoiceStorage, IInvoiceStorage<EVT>
public class FacturaStorageForMySQLServer : IInvoiceStorage, IInvoiceStorage<EVTFruit>

这样你就可以在invoice_service类中使用非通用版本的接口。

但是,正如我所说,根据您的需要,如果您可以使该接口的功能独立于类型(例如,List<T>也为列表功能实现IList,没有类型)。

答案 2 :(得分:0)

在尝试了你的建议并阅读了一些博客之后,这就是我所做的,并且至少在目前正在实现我的要求。当我意识到我不应该将通用存储库模式用作存储库本身而是作为存储库的帮助程序时,问题就解决了!最后,我正在做的是将通用接口包装在另一层非通用接口中。

调用IInvoiceRepositoryService实现的Service类

public class InvoiceService
{
   private IInvoiceRepositoryService RepositoryService;
   public SQLInvoiceService(IInvoiceRepositoryService _RS)
   {
       RepositoryService=_RS;
   }
}

及其各自对EVT和EVTFruit的实施。

public class EVTRepository:IInvoiceRepositoryService
{
  private IInvoiceStorage<EVT> EVTStorage;

  public EVTInvoiceRepository(IInvoice<EVT> _EVT)
  {
    EVTStorage=_EVT;
  }
}


public class EVTStorageForSQLServer: IInvoiceStorage<EVT>
{
   /*Implementation*/
}

public class EVTStorageForMySQLServer: IInvoiceStorage<EVT>
{
   /*Implementation*/
}



public class EVTFruitRepository:IInvoiceRepositoryService
{
  private IInvoiceStorage<EVT> EVTFruitStorage;

  public EVTFruitInvoiceRepository(IInvoice<EVTFruit> _EVTFruit)
  {
    EVTFruitStorage=_EVTFruit;
  }
}

public class EVTFruitStorageForSQLServer: IInvoiceStorage<EVTFruit>
{
   /*Implementation*/
}

public class EVTFruitStorageForMySQLServer: IInvoiceStorage<EVTFruit>
{
   /*Implementation*/
}

最后,我认为这只是一个设计问题。我要将Ron Beyer的回答标记为答案,因为它是有效的,而且非常简单