基于IoC的ControllerFactory

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);
        }
    }
}
Employee
    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 = "");
    }
EmployeeRepository
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);

        }

    }
}

两个页面的代码:

EmployeeDetail.cshtml
@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>
EmployeeList.cshtml
@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>

路由注册:

RouteConfig
    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);

结果展示:

原文地址:https://www.cnblogs.com/hailiang2013/p/2882993.html