【问题标题】:Inheritance and derived classes in C# (DI case)C# 中的继承和派生类(DI 案例)
【发布时间】:2018-03-14 19:31:12
【问题描述】:

所以我正在关注关于在 C# 中使用 Unity 进行依赖注入的教程。在本教程中,他们使用存储库类作为示例来演示该概念。试图将其应用于示例项目之一,我遇到了继承问题。所以我有

public interface IRepository<T> where T : class
{
    List<T> GetAll();

    T Get(int id);

    void Add(T entity);

    void SaveChanges();
}

public class Repository<T> : IRepository<T> where T : class
{
    private CoffeeMachineDbContext context = null;

    protected virtual DbSet<T> DbSet { get; set; }

    public Repository()
    {
        context = new CoffeeMachineDbContext();
        DbSet = context.Set<T>();
    }

    public Repository(CoffeeMachineDbContext context)
    {
        this.context = context;
    }

    public virtual List<T> GetAll()
    {
        return DbSet.ToList();
    }

    public virtual T Get(int id)
    {
        return DbSet.Find(id);
    }

    public virtual void Add(T entity)
    {
        DbSet.Add(entity);
    }

    public void SaveChanges()
    {
        context.SaveChanges();
    }
}

存储库类实现接口和常用方法。 现在为了能够按照解释(或者至少按照我的理解)应用依赖注入,我创建了一个名为 IClientRepository 的新接口,它继承自 IRepository,如下所示:

public interface IClientRepository : IRepository<Client>
{
    Order GetLastOrder(int id);
}

请注意,接口声明了一个特定于客户端上下文的新方法。

最后,IClientRepository接口的实现是:

public class ClientRepository : Repository<Client>, IClientRepository
{
    /// <summary>
    /// Gets the client's last order
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public Order GetLastOrder(int id)
    {
        Order lastOrder = null;
        Client client = DbSet.Find(id);
        if (client != null)
        {
            lastOrder = client.Orders.OrderByDescending(o => o.DateCreated).FirstOrDefault();
        }

        return lastOrder;
    }

我不需要实现 IRepository 方法,因为它们在所有其他方法中是通用的。

我面临的问题是,当我尝试在统一容器中注册类型时,如下所示:

container.RegisterType<IClientRepository, ClientRepository>(new HierarchicalLifetimeManager());

我收到以下错误

类型“CoffeeMachine.Models.Repositories.ClientRepository”不能用作泛型类型或方法“UnityContainerExtensions.RegisterType(IUnityContainer, LifetimeManager, params InjectionMember[])”中的类型参数“TTo”。 没有从“CoffeeMachine.Models.Repositories.ClientRepository”到“CoffeeMachine.Models.Repositories.IClientRepository”的隐式引用转换

有人知道我在这里做错了什么吗?

【问题讨论】:

  • 为什么你的 ClientRepository 没有实现 IClientRepository?
  • 因为当我这样做时,我得到错误:ClientRepository 没有实现 GetAll()、Get(int) 等。
  • 它认为你需要基类接口:public class ClientRepository : Repository&lt;Client&gt;, IClientRepository {...}
  • 一个 IClientRepository 是一个 IRepository。存储库是 IRepository。 ClientRepository 是一个存储库。但是根据您的代码, ClientRepository 不是 IClientRepository 。就像狗是动物,猫是动物一样,拉布拉多犬是狗和动物,但拉布拉多犬不是猫。
  • 拥有特定于实体的存储库抽象,例如 IClientRepository 是个坏主意,如 this article 中所述。

标签: c# asp.net .net inheritance dependency-injection


【解决方案1】:

发生该错误是因为您的类实际上并未实现 IClientRepository

只有当实例的类实际实现了接口时,才能将实例转换为接口。

【讨论】:

  • 一开始我也是这么想的。但是,一旦我这样做了,我就会得到错误:ClientRepository 没有实现 GetAll()、Get(int) 等...
猜你喜欢
  • 2021-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多