首次实施:
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 原则在代码中的应用之一。
这是我对此的疑问:
第一个实现(依赖注入)是否更符合依赖倒置原则?
实际意义是什么,特别是在灵活性、可测试性和性能方面,同时还考虑了 SOLID 原则。
是否存在一种方法比另一种方法更适合的场景?
我将不胜感激任何关于这种情况下依赖注入最佳实践的见解或指导。谢谢!
使用依赖注入的第一个实现是否更符合依赖倒置原则?
尽管依赖注入(DI)和依赖倒置原则(DIP)中都出现了依赖这个词,但它们是独立的(尽管有些相关)想法。
第一个代码替代方案确实使用了构造函数注入设计模式 - 最常见的 DI 模式。也遵循DIP吗?
从例子中我们无法真正看出,因为DIP是一个关于抽象的原则:
抽象不应依赖于细节。细节应该取决于抽象。
[...]客户端[...]拥有抽象接口
-APPP
这里是这样吗?我无法从OP中看出。
Delete
方法存在于 IGenericDal<T>
上是因为客户端代码需要它,还是因为实现能够提供该方法?
总的来说,我对公开或使用实体框架 (EF)(或任何其他 ORM)或“实体类”的任何接口或基类持高度怀疑态度。此类类型往往会自动违反 DIP,这也要求
高层模块不应该依赖于低层模块。两者都应该依赖于抽象。
鉴于实践中
T
方法中的 Delete
将是一个“实体类”,并且实体类有各种各样的约束,我将此类类视为低级模块。因此,高层模块 (IGenericDal<T>
) 事实上依赖于低层模块(实体类,或 EF 本身)。因此,我认为这是 DIP 违规。