依赖注入和仓储模式的区别

11

我正在尝试理解依赖注入和仓储模式之间的区别。

根据我的理解,除了在依赖注入中使用构造函数注入之外,仓储模式可以完成所有依赖注入所做的事情。

好的,让我试着给出一个例子来解释:(请注意,我在使用Unity框架进行依赖注入)

创建Product类

public class Product
{
 public int Id { get; set; }
 public string Name { get; set; }
 public string Category { get; set; }
 public decimal Price { get; set; }
}

在模型上创建接口

public interface IProductRepository
{
 IEnumerable<Product> GetAll();
 Product Get(int id);
 Product Add(Product item);
 bool Update(Product item);
 bool Delete(int id);
}

实现接口

//ProductRepository.cs
public class ProductRepository : IProductRepository
{
 private List<Product> products = new List<Product>();
 private int _nextId = 1;

 public ProductRepository()
 {
 // Add products for the Demonstration
 Add(new Product { Name = "Computer", Category = "Electronics", Price = 23.54M });
 Add(new Product { Name = "Laptop", Category = "Electronics", Price = 33.75M });
 Add(new Product { Name = "iPhone4", Category = "Phone", Price = 16.99M });
 }

 public IEnumerable GetAll()
 {
 // TO DO : Code to get the list of all the records in database
 return products;
 }
 public Product Get(int id)
 {
 // TO DO : Code to find a record in database
 return products.Find(p => p.Id == id);
 }
 public Product Add(Product item)
 {
 if (item == null)
 {
 throw new ArgumentNullException("item");
 }

 // TO DO : Code to save record into database
 item.Id = _nextId++;
 products.Add(item);
 return item;
 }
 public bool Update(Product item)
 {
 if (item == null)
 {
 throw new ArgumentNullException("item");
 }

 // TO DO : Code to update record into database
 int index = products.FindIndex(p => p.Id == item.Id);
 if (index == -1)
 {
 return false;
 }
 products.RemoveAt(index);
 products.Add(item);
 return true;
 }
 public bool Delete(int id)
 {
 // TO DO : Code to remove the records from database
 products.RemoveAll(p => p.Id == id);
 return true;
 }
}

在Bootstrap.cs中初始化依赖项注入(DI)

private static IUnityContainer BuildUnityContainer()
{
 var container = new UnityContainer();

 // register all your components with the container here
 // it is NOT necessary to register your controllers

 container.RegisterType<IProductRepository, ProductRepository>();

 // e.g. container.RegisterType<ITestService, TestService>(); 

 RegisterTypes(container);

 return container;
}

控制器

public class ProductController : Controller
{
 readonly IProductRepository repository;

 //inject dependency
 public ProductController(IProductRepository repository)
 {
 this.repository = repository; 
 }

 public ActionResult Index()
 {
 var data = repository.GetAll();
 return View(data);
 }
 //Other Code
}

我的问题

  • 仓储模式和DI之间有什么区别?
  • 构造函数注入的优点是什么?
  • 如果有人能尽可能详细地解释Bootstrap.cs文件代码和Controller类代码,我将不胜感激。

代码来源:http://www.dotnet-tricks.com/Tutorial/dependencyinjection/632V140413-Dependency-Injection-in-ASP.NET-MVC-4-using-Unity-IoC-Container.html


5
“Repository Pattern” 和 “DI” 之间的区别是两种不同的概念,这是一种不恰当的比较。 - McGarnagle
@McGarnagle 谢谢。我的例子主要是创建存储库,这里唯一不同的是使用构造函数注入(DI)来实现IOC。我的问题是这样做有什么好处?感谢您的见解。 - Lynnw
1
依赖注入意味着给一个对象它的实例变量。如果你仔细阅读了IOC,简而言之,它只是要求添加一个接口来创建抽象,这也是存储库模式所做的...这就是我问diff的原因。在StackOverflow这里的问题是人们非常死板,这完全是基于我收到的评论的感觉。当你不知道答案时,发表评论的原因是什么?只是为了获得额外的积分来炫耀你的老板吗? - Lynnw
我并不是在刻意挑衅,我马上就会提交自己对你问题的回答... - McGarnagle
2个回答

14

它们确实不可比较,仓库是您可以通过依赖注入注入的东西。 DI 的目的是使应用程序松耦合。您可以指定一个定义了实现必须满足的合同的接口,而不是指定具体实现。这样,您可以更轻松地替换实现。

由 Martin Fowler 定义的存储库模式将您的域与如何实现存储无关,因此检索的所有对象都可以像内存集合一样处理。您可以基于数据库、XML 文件、文本文档或任何其他东西创建存储库。应用程序代码本身并不关心。这使得它非常适用于测试,因此与 TDD 相关。

您将依赖项(注入)传递给控制器。这些可能是存储库、服务或控制器所需的任何内容。您的 IoC 容器在运行时将所有这些连接在一起。这本身就非常强大,我们在 SaaS 应用程序中大量使用 DI,在其中客户拥有自己的实现,根据客户条件性地注入。

我建议您阅读.NET 中的依赖注入。 Mark Seemann 可以比我更好地解释这一点,并且是介绍您应该使用 DI 和各种IoC 容器(例如 Unity)的方法和原因的优秀介绍。


1
谢谢。我的例子主要是创建存储库,这里唯一不同的是使用构造函数注入(DI)来实现IOC。我的问题是这样做有什么好处?感谢您的见解。 - Lynnw

5

仓储模式和DI有何区别?

我认为你无法进行有意义的比较。它们都是编程技术,但它们来自非常不同的考虑因素。(参见仓储模式, 依赖注入)

我想你可以这样说:数据仓库是外部依赖的一个例子,您的DI框架通常会将其注入到需要它的对象中。

构造器注入的优点是什么?

您是指相对于其他注入模式而言吗?那么:构造器注入允许您在对象首次初始化时访问注入的依赖项。

或者您是指使用DI的优点是什么?这是一个非常广泛的问题,但我会说:为您的应用程序提供一致的结构,并减少其组件之间的严格耦合。

感谢你能解释一下 Bootstrap.cs 文件代码和 Controller 类代码,尽可能详细地解释。
"Bootstrapper" 类在 Unity 中类似于 Ninject 中的 "Kernel" 类,实现了 DI 模式的所谓 "组合层"。这是你告诉你的 DI 容器它应该如何解决在整个应用程序中找到的所有依赖项的地方。这基本上意味着将注入接口与它们的实现匹配,并提供有关注入对象范围的说明(即单例、每个请求或瞬态)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接