IoC:
所谓控制反转,简单的说,就是应用本身不负责依赖对象的创建和维护,而交给一个外部容器来负责,这样控制权就由应用转移到了外部IoC容器,控制权实现了所谓的反转。
例如:在类型A中要使用类型B的实例,而B的实例创建并不是由A来负责,而是通过外部容器来创建,通过IoC的方式实现针对目标Controller的激活具有重要意义。
Controller与Model 分离
ASP.NET MVC 所谓的Model仅仅表示绑定到View 上的数据,我们一般称之为ViewModel,而真正意义上的Model一般指维护应用状态和提供业务功能操作的领域模型,或者针对业务层的入口或者业务服务的代理
基于IoC的ControllerFactory
主要是通过IoC容器对目标Controller的激活
由于ControllerFactory包括了对Controller类型的解析、Controller实例的创建与释放及会话状态行为选项的获取。
一般来说Controller实例的创建才需要IoC容器的控制,为了避免重新实现其他功能,这里直接继承DefaultControllerFactory,重写Controller实例的创建
Demo:创建基于Unity的ControllerFactory
新建一项目:
using System; using System.Web.Mvc; using Microsoft.Practices.Unity; namespace MvcApplication3.Unity { public class UnityControllerFactory:DefaultControllerFactory { public IUnityContainer UnityContainer { get; private set; } public UnityControllerFactory(IUnityContainer unityContainer) { this.UnityContainer = unityContainer; } protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType) { if (null==controllerType) { return null; } return (IController)this.UnityContainer.Resolve(controllerType); } } }

public class Employee { public string Id { get; private set; } public string Name { get; private set; } public string Gender { get; private set; } public DateTime BirthDate { get; private set; } public string Department { get; private set; } public Employee(string id, string name, string gender, DateTime birthdate, string department) { this.Id = id; this.Name = name; this.Gender = gender; this.BirthDate = birthdate; this.Department = department; } }
创建一个EmployeeRepository对象来进行数据获取,并为它定义了对应的接口IEmployeeRepository
public interface IEmployeeRepository { IEnumerable<Employee> GetEmployees(string id = ""); }

using System; using System.Collections.Generic; using System.Linq; using MvcApplication3.IModels; using MvcApplication3.ViewModel; namespace MvcApplication3.Model { public class EmployeeRepository:IEmployeeRepository { public static IList<Employee> employees; static EmployeeRepository() { employees = new List<Employee>(); employees.Add(new Employee("001","张三","男",new DateTime(2011,5,10),"销售部")); employees.Add(new Employee("002","李四","女",new DateTime(1987,4,2),"技术部")); employees.Add(new Employee("003","王五","男",new DateTime(1932,3,6),"财务部")); employees.Add(new Employee("004","赵六","女",new DateTime(1988,5,3),"人事部")); employees.Add(new Employee("005","老八","男",new DateTime(1990,6,5),"销售部")); } public IEnumerable<Employee> GetEmployees(string id = "") { return employees.Where(e => e.Id == id || string.IsNullOrEmpty(id)); } } }
创建一个EmployeeController,它具有一个类型为IEmployeeRepository的属性Repository,应用Dependency特性,告诉我们这是一个“依赖属性”,当我们采用UnityContainer来激活EmployeeController对象的时候,会根据注册的类型映射来实例化一个实现了IEmployeeRepository的类型的实例来初始化该属性
using System.Linq; using System.Web; using System.Web.Mvc; using Microsoft.Practices.Unity; using MvcApplication3.IModels; using MvcApplication3.ViewModel; namespace MvcApplication3.Controllers { public class EmployeeController : Controller { [Dependency] public IEmployeeRepository Repository { get; set; } public ActionResult GetAllEmployees() { var employees = this.Repository.GetEmployees(); return View("EmployeeList", employees); } public ActionResult GetEmployeeById(string id) { Employee employee = this.Repository.GetEmployees(id).FirstOrDefault(); if (null==employee) { throw new HttpException(404, string.Format("ID为{0}的员工不存在", id)); } return View("EmployeeDetail", employee); } } }
两个页面的代码:

@model MvcApplication3.ViewModel.Employee <html> <head> <title> @Model.Name </title> </head> <body> <table> <tr> <td> @Html.LabelFor(m=>m.Id) </td> <td> @Html.DisplayFor(m=>m.Id) </td> </tr> <tr> <td> @Html.LabelFor(m=>m.Name) </td> <td> @Html.DisplayFor(m=>m.Name) </td> </tr> <tr> <td> @Html.LabelFor(m=>m.Gender) </td> <td> @Html.DisplayFor(m=>m.Gender) </td> </tr> <tr> <td> @Html.LabelFor(m=>m.BirthDate) </td> <td> @Html.DisplayFor(m=>m.BirthDate) </td> </tr> <tr> <td> @Html.LabelFor(m=>m.Department) </td> <td> @Html.DisplayFor(m=>m.Department) </td> </tr> </table> </body> </html>

@model IEnumerable<MvcApplication3.ViewModel.Employee> <html> <head> <title>员工列表 </title> </head> <body> <table> <tr> <th>姓名</th> <th>性别</th> <th>出生日期</th> <th>部门</th> </tr> @{ foreach (MvcApplication3.ViewModel.Employee e in Model) { <tr> <td> @Html.ActionLink(e.Name, "GetEmployeeById", new { name = e.Name, e.Id }) </td> <td> @Html.DisplayFor(em => e.Gender) </td> <td> @Html.DisplayFor(em => e.BirthDate) </td> <td> @Html.DisplayFor(em => e.Department) </td> </tr> } } </table> </body> </html>
路由注册:

public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.MapRoute( name: "Home", url: "", defaults: new { controller = "Employee", action = "GetAllEmployees", id = UrlParameter.Optional } ); routes.MapRoute( name: "Detail", url: "{name}/{id}", defaults: new { controller = "Employee", action = "GetEmployeeById" } ); } }
注册接口与实现接口的类型映射:
UnityContainer unityContainer = new UnityContainer(); unityContainer.RegisterType<IEmployeeRepository, EmployeeRepository>(); UnityControllerFactory controllerFactory = new UnityControllerFactory(unityContainer); ControllerBuilder.Current.SetControllerFactory(controllerFactory);
结果展示: