原文链接: http://www.codeproject.com/Articles/838097/CRUD-Operations-Using-the-Generic-Repository-Pat
(PS本来这篇博客是我快翻译好了,结果浏览器崩溃,坑爹啊。现在不写了)
Dependency Injection (DI) is a type of IoC, it is a pattern where objects are not responsible for creating their own dependencies. Dependency injection is a way to remove hard-coded dependencies among objects, making it easier to replace an object's dependencies, either for testing (using mock objects in unit test) or to change run-time behaviour.
依赖注入,是控制反转的一种类型,是一种设计模式,即对象不负责创建它们自己的依赖。依赖注入是一种删除对象之间的硬编码依赖关系,使其更容易替换对象的依赖项,或者为了测试(在单元测试中,使用模拟对象),或者为了改变其运行时的行为。
Before understanding Dependency Injection, you should be familiar with the two concepts of Object Oriented Programming, one is tight coupling and another is loose coupling, so let's see each one by one.
在理解依赖注入之前,你应该熟悉面向对象编程中的两个概念,一个是紧耦合,另外一个是松耦合,我们来一个一个看吧。
It means two objects are independent and an object can use another object without being dependent on it. It is a design goal that seeks to reduce the inter-dependencies among components of a system with the goal of reducing the risk that changes in one component will require changes in any other component.
它意味着,两个对象是独立的,一个对象可以使用另外的一个对象,而不用依赖在其基础上。这是一个设计的目标,旨在减少系统组件相互之间的依赖关系,即减少风险的目标---在我们改变一个组件的时候,将会需要另外一个组件的变化。
Now in short, Dependency Injection is a pattern that makes objects loosely coupled instead of tightly coupled. Generally, we create a concrete class object in the class we require the object and bind it in the dependent class but DI is a pattern where we create a concrete class object outside this high-level module or dependent class.
现在,简单来说,依赖注入是一个设计模式,它使得对象之间变得松耦合而不是紧耦合。通常地,我们创建在一个类中,创建具体的类的对象的时候,我们需要这个对象在这个类中(即附属于这个类),但是依赖注入是一个模式,在这个模式中,我们创建一个具体的类的对象,在高级模块的外面或者在这个类的外面。
There are three types of dependency injections:
这里有三种类型的依赖注入:
In this article, we will use Constructor Dependency Injection. This is the most commonly used Dependency Injection Pattern in Object Oriented Programming. The Constructor Dependency Injection uses a parameter to inject dependencies so there is normally one parameterized constructor always. So in this constructor dependency, the object has no default constructor and you need to pass specified values at the time of creation to initiate the object. You can say that your design is loosely coupled with the use of constructor dependency injection.
在这个文章中,我们将会使用构造函数的依赖注入方式。这是在面向对象编程中,最常用的依赖注入方式。构造函数的依赖注入方式,使用一个参数来注入依赖,所以通常会是带一个参数的构造函数。因此在构造函数依赖注入中,对象没有默认的构造函数,并且你需要在创建对象的时候,去传递一个指定的值,来初始化这个对象,你可以说你的设计是松耦合的,因为你使用了构造函数的依赖注入。
The Dependency Injection Container is a framework to create dependencies and inject them automatically when required. It automatically creates objects based on requests and injects them when required. It helps us split our application into a collection of loosely-coupled, highly-cohesive pieces and then glue them back together in a flexible manner. By DI container, our code will become easier to write, reuse, test and modify. In this article, we will use a Niject DI Container.
这个依赖注入容器是一个框架,来创建依赖,并在需要的时候,自动注入依赖。它自动根据需要创建对象,并且在需要的时候,注入他们。它帮助我们,拆分我们的程序,变成松耦合的,高内聚的片段,然后以灵活的方式拼凑在一起。通过依赖注入容器,我们的代码,将会变得很容易写,很好的重用性,很容易测试,并且很容易修改。在这个文章中,我们将会使用Niject 依赖注入容器。
We create four projects in a solution to implement DIP with generic repository pattern. These are:
我们在解决方案中,创建四个项目通过使用泛型仓储模式来实现依赖倒置(DIP--Dependency Inversion Principle),他们是:
Ioc.Core
(class library)--类库 Ioc.Data
(class library)--类库 Ioc.Service
(class library)--类库 Ioc.Web
(web application)--web应用程序
In this article, we are working with the Entity Framework Code First Approach so the project Ioc.Core
contains entities that are necessary in the application's database. In this project, we create three entities, one is the BaseEntity
class that has common properties that will be inherited by each entity and the others are User
and UserProfile
entities. Let's see each entity. The following is a code snippet for the BaseEntity
class.
在这个文章中,我们使用EF Code First方法,所以这个Ioc.Core包含了这个程序的数据库必须的实体。在这个项目中,我们创建三个实体,一个是BaseEntity,它有公共的属性,将会被每一个实体和另外的两个实体( User和UserProfile继承
)。我们来一个一个看,首先看BaseEntity实体类。
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace Ioc.Core 8 { 9 public abstract class BaseEntity 10 { 11 public Int64 ID { get; set; } 12 13 public DateTime AddedDate { get; set; } 14 15 public DateTime ModifiedDate { get; set; } 16 17 public string IP { get; set; } 18 } 19 }BaseEntity
The User
and UserProfile
entities have a one-to-one relationship. One User can have only one profile.
User和UserProfile实体之间是一对一的关系,一个user只能有一个profile。
Now, we create a User entity under the Data folder of the Ioc.Core
project that inherits from the BaseEntity
class. The following is a code snippet for the User entity.
现在,我们在Ioc.Core项目中创建Data文件夹,然后在Data文件夹下面,创建User实体,继承BaseEntity。请看下面的代码:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace Ioc.Core.Data 8 { 9 public class User:BaseEntity 10 { 11 public string UserName { get; set; } 12 13 public string Email { get; set; } 14 15 public string Password { get; set; } 16 17 public virtual UserProfile UserProfile { get; set; } 18 } 19 }User
Now, we create a UserProfile
entity under the Data folder of the Ioc.Core
project that inherits from the BaseEntity
class. The following is a code snippet for the UserProfile
entity.
现在,我们在Ioc.Core项目中创建Data文件夹,然后在Data文件夹下面,创建UserProfile实体,继承BaseEntity。请看下面的代码:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace Ioc.Core.Data 7 { 8 public class UserProfile 9 { 10 public string FirstName { get; set; } 11 12 public string LastName { get; set; } 13 14 public string Address { get; set; } 15 16 public virtual User User { get; set; } 17 18 19 } 20 }UserProfile
The Ioc.Data
project contains DataContext
, User
and UserProfile
entities Mapping
and Repository
. The ADO.NET Entity Framework Code First data access approach requires us to create a data access context class that inherits from the DbContext
class so we create an interface IDbContext
that inherited by context class IocDbContext
( IocDbContext.cs ) class. In this class, we override the OnModelCreating()
method. This method is called when the model for a context class ( IocDbContext
) has been initialized, but before the model has been locked down and used to initialize the context such that the model can be further configured before it is locked down. First, create an IDbContext
interface and the following code snippet for it.
Ioc.Data项目包含数据上下文,User,和Userprofile实体,Mapping和Repository.ADO.NET EF CodeFirst 数据访问方法,需要我们去创建一个数据访问上下文类,继承自DbContext类,所以我们可以创建一个接口IDbContext,被Context类(IocDbContext.CS)继承,我们重写这个OnModelCreating()方法,当上下文类(IocDbContext)已经被初始化的时候,这个方法就会被调用,但是在model被锁住之前,去初始化这个上下文,这个时候,这个model能够被进一步的配置,在被Locked down之前。首先,创建一个IDbContext接口:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 using System.Data.Entity; 8 using Ioc.Core; 9 10 namespace Ioc.Data 11 { 12 public interface IDbContext 13 { 14 IDbSet<TEntity> Set<TEntity>() where TEntity : BaseEntity; 15 16 int SaveChanges(); 17 } 18 }IDbContext