了解通用存储库实现中的依赖注入

问题描述 投票:0回答:1

首次实施:

public class GenericRepository<T> : IGenericDal<T> where T : class
{
    private readonly Context _context;

    public GenericRepository(Context context)
    {
        _context = context;
    }

    public void Delete(T entity)
    {
        _context.Set<T>().Remove(entity);
        _context.SaveChanges();
    }
}

第二次实施:

public class GenericRepository<T> : IGenericDal<T> where T : class
{
    public void Delete(T entity)
    {
        using var context = new Context();
        context.Set<T>().Remove(entity);
        context.SaveChanges();
    }
}

在第一个实现中,我使用依赖注入通过构造函数传递数据库上下文(Context),而在第二个实现中,我在内部创建一个新的上下文。

据我所知,使用关键字无需等待垃圾收集器即可删除源,这很好,另一方面,依赖注入实现了依赖倒置原则,这就是 SOLID 原则在代码中的应用之一。

这是我对此的疑问:

  1. 第一个实现(依赖注入)是否更符合依赖倒置原则?

  2. 实际意义是什么,特别是在灵活性、可测试性和性能方面,同时还考虑了 SOLID 原则。

  3. 是否存在一种方法比另一种方法更适合的场景?

我将不胜感激任何关于这种情况下依赖注入最佳实践的见解或指导。谢谢!

c# asp.net-mvc entity-framework entity-framework-core
1个回答
0
投票

使用依赖注入的第一个实现是否更符合依赖倒置原则?

尽管依赖注入(DI)和依赖倒置原则(DIP)中都出现了依赖这个词,但它们是独立的(尽管有些相关)想法。

第一个代码替代方案确实使用了构造函数注入设计模式 - 最常见的 DI 模式。也遵循DIP吗?

从例子中我们无法真正看出,因为DIP是一个关于抽象的原则:

抽象不应依赖于细节。细节应该取决于抽象。

[...]客户端[...]拥有抽象接口

-APPP

这里是这样吗?我无法从OP中看出。

Delete
方法存在于
IGenericDal<T>
上是因为客户端代码需要它,还是因为实现能够提供该方法?

总的来说,我对公开或使用实体框架 (EF)(或任何其他 ORM)或“实体类”的任何接口或基类持高度怀疑态度。此类类型往往会自动违反 DIP,这也要求

高层模块不应该依赖于低层模块。两者都应该依赖于抽象。

鉴于实践中

T
方法中的
Delete
将是一个“实体类”,并且实体类有各种各样的约束,我将此类类视为低级模块。因此,高层模块 (
IGenericDal<T>
) 事实上依赖于低层模块(实体类,或 EF 本身)。因此,我认为这是 DIP 违规。

© www.soinside.com 2019 - 2024. All rights reserved.