在MVC3项目中结合NInject实现依赖注入

 

解释:

依赖注入:(Dependency Injection),也称之为控制反转。

大致意思就是,让我们的应用程序所依赖的一些外部服务,可以根据需要动态注入,而不是预先在应用程序中明确的约束.这种思想在当前软件开发领域,为了保证软件架构灵活性和可便于维护性,应该说是很有意义的。在MVC框架中,为依赖注入的设计提供了先天的支持。结合一些我们熟知的DI组建,比如Unity,Ninject等等。可以较为容易的实现上述提到的功能。

 

场景介绍:
我们的应用程序,需要支持各种不同的数据源,而且我们希望日后可以很容易地切换,不会因为数据源的变化而导致对Contoller或者Model,或者View做修改。

第一步准备一个MVC项目(选择空模板)

第二步准备一个实体模型

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SportsStore.Domain.Entities
{
    public class Employee
    {
        public int ID { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
}

第三步:定义一个数据访问接口

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SportsStore.Domain.Entities;

namespace SportsStore.Domain.Abstract
{
    public interface IEmployeeRepository
    {
        IQueryable<Employee> Employees { get; }
    }
}

第四步:添加一个HomeController

 public class HomeController : Controller
    {
        //
        // GET: /Home/

        public ActionResult Index()
        {
            return View();
        }

    }

注意,这里需要为HomeController添加一个特殊的构造函数,传入IEmployeeRepository这个接口。通常,所有的DI组件都是通过这样的方式注入的。
在设计HomeController的时候,我们不需要关心到底日后会用具体的哪种IEmployeeRepository,我们只是要求要传入一个IEmployeeRepository的具体实现就可以了,这就是DI的本质了。

 

到这里为止,我们该做的准备工作基本就绪了。下面来看看如何结合DI组件来实现我们的需求

第五步:引入NInject组件


这是我比较喜欢的一个DI组件。它还针对MVC3专门有一个扩展

第六步:创建一个IEmployeeRepository的具体实现

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SportsStore.Domain.Abstract;
using SportsStore.Domain.Entities;

namespace SportsStore.Domain.Concrete
{
    public class EmployeeRepository : IEmployeeRepository
    {
        public IQueryable<Employee> Employees
        {
            get
            {
                return new[] { new Employee { ID = 1, FirstName = "ICEY", LastName = "chen" } }.AsQueryable();
            }
        }
    }
}

第七步:实现注入,通过扩展MVC组件实现

第一种:实现自定义ControllerFactory

 

我们都知道,Controller其实都是由ControllerFactory来生成的,那么,为了给所有新创建从Controller都自动注入我们的服务,那么就可以从ControllerFactory这个地方动动脑筋了。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Ninject;
using Moq;
using SportsStore.Domain.Abstract;
using SportsStore.Domain.Entities;
using SportsStore.Domain.Concrete;
using System.Configuration;
using SportsStore.WebUI.Infrastructure.Abstract;
using SportsStore.WebUI.Infrastructure.Concrete;


namespace SportsStore.WebUI.Infrastructure
{

    /// <summary>
    /// 使用Ninject生成mvc应用程序controller并处理DI
    /// </summary>
    public class NinjectControllerFactory:DefaultControllerFactory
    {
        private IKernel ninjectKernel;
        public NinjectControllerFactory()
        {
            ninjectKernel = new StandardKernel();
            AddBindings();
        }

        protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
        {
            return controllerType == null
                ? null
                : (IController)ninjectKernel.Get(controllerType);
        }
        
        private void AddBindings()
        {
            ninjectKernel.Bind<IEmployeeRepository>().To<EmployeeRepository>();
        }
    }
}

要使用这个自定义的 ControllerFactory,我们需要修改Global.ascx文件中的Application_Start方法,添加下面的代码

ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());

这样做好之后,我们可以测试HomeController中的Index这个Action,我们发现它还是能正常工作。

修改HomeController中的Index

public class HomeController : Controller
    {

        private IEmployeeRepository repository;
        public HomeController(IEmployeeRepository employeeRepository)
        {
            repository = employeeRepository;
        }
        public ActionResult Index()
        {
            return View(repository.Employees);
        }
    }

运行程序,我们发现程序能很好的工作了。

第二种:实现自定义的DependencyResolver

 

顾名思义,这就是MVC框架里面专门来处理所谓的依赖项的处理器。可以说这是MVC专门为DI准备的一个后门。下面是我写好的一个例子

public class NinjectDependencyResolver : IDependencyResolver
    {
        private IKernel kernel;
      
        public NinjectDependencyResolver()
        {
            kernel = new StandardKernel();
            AddBindings();
        }

        public object GetService(Type serviceType)
        {
            return kernel.TryGet(serviceType);
        }

        public IEnumerable<object> GetServices(Type serviceType)
        {
            return kernel.GetAll(serviceType);
        }

        public IBindingToSyntax<T> Bind<T>()
        {
            return kernel.Bind<T>();
        }
        public IKernel Kernel
        {
            get { return kernel; }
        }

        private void AddBindings()
        {
            Bind<IEmployeeRepository>().To<EmployeeRepository>();
        }
    }

那么,如何使用这个自定义的处理器呢?


很简单,我们仍然是修改Global.asax文件中的Application_Start方法 DependencyResolver.SetResolver(new NinjectDependencyResolver());

请注意,之前那个设置ControllerFactory的代码,我们可以注释掉了

 

 

至此,Ninject注入容器完全融入MVC的心脏了。

 

转载于:https://www.cnblogs.com/crystal159/archive/2012/07/11/2586306.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值