ASP.NET MVC5 采用Unity(代码和配置文件两种方式)实现IOC

Unity是微软Patterns & Practices团队所开发的一个轻量级的,并且可扩展的依赖注入(Dependency Injection)容器,通过使用Unity,我们能轻松构建松耦合结构的程序,从而让整个程序框架变得清晰和易于维护。下面我通过两个具体的mvc的例子来说明一下怎么用代码和配置文件来实现IOC。

1、用编程方式实现注入

使用Unity来管理对象与对象之间的关系可以分为以下几步:

      A、创建一个UnityContainer对象

      B、通过UnityContainer对象的RegisterType方法来注册对象与对象之间的关系

      C、通过UnityContainer对象的Resolve方法来获取指定对象关联的对象

 

2、配置文件方式

通过配置文件配置Unity信息需要有以下几个步骤:

       A、在配置文件<configSections> 配置节下注册名为unity的section

       B、在<configuration> 配置节下添加Unity配置信息

       C、在代码中读取配置信息,并将配置载入到UnityContainer中

 

一,测试数据准备:

1.1、创建ASP.NET MVC项目(ioc)和三个类库(IInterFace,IService,Model),如图:

ioc为UI层:

:记得引用其他类库:

 

1.2、ioc.IInterFace为抽象层(接口):这里写了两个接口(IUser和IStudent)

1、IUser用于测试:只使用代码,不使用配置文件实现IOC

2、IStudent用于测试:使用配置文件实现IOC

IStudent 接口代码:

using ioc.Model;<br/>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ioc.IInterFace
{
    public interface IStudent
    {
        IEnumerable<Student> GetAll();
        Student Get(int id);
        Student Add(Student item);
        bool Update(Student item);
        bool Delete(int id);
    }
}

IUser 接口代码:

using ioc.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ioc.IInterFace
{
   public interface IUser
    {
        List<UserInfo> GetUsers();
    }
}

 

1.3、ioc.IService为业务层(继承对应抽象类):这里创建两个实现类(SimpleStudent,SimpleUser)

SimpleStudent 类(继承自IStudent)代码:

using ioc.IInterFace;
using ioc.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ioc.IService
{
   public class SimpleStudent : IStudent
    {
        private readonly List<Student> Articles = new List<Student>();

        public SimpleStudent()
        {
            //添加演示数据
            Add(new Student { Id = 1, Name = "大司马", Major = "软件工程", Graduation = "2021年", School = "清华大学" });
            Add(new Student { Id = 2, Name = "茄子", Major = "计算机科学与技术", Graduation = "2021年", School = "清华大学" });
            Add(new Student { Id = 3, Name = "呆妹", Major = "自动化", Graduation = "2021年", School = "清华大学" });
        }

        /// <summary>
        /// 添加文章
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public Student Add(Student item)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item is null");
            }
            Articles.Add(item);
            return item;
        }



        /// <summary>
        /// 获取全部文章
        /// </summary>
        /// <returns></returns>
        public IEnumerable<Student> GetAll()
        {
            return Articles;
        }
        /// <summary>
        /// 通过ID获取文章
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Student Get(int id)
        {
            return Articles.Find(p => p.Id == id);
        }



        /// <summary>
        /// 更新文章
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public bool Update(Student item)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }

            int index = Articles.FindIndex(p => p.Id == item.Id);
            if (index == -1)
            {
                return false;
            }
            Articles.RemoveAt(index);
            Articles.Add(item);
            return true;
        }


        /// <summary>
        /// 删除文章
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public bool Delete(int id)
        {
            Articles.RemoveAll(p => p.Id == id);
            return true;
        }


    }
}

 

SimpleUser(继承自IUser)类代码:

using ioc.IInterFace;
using ioc.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;


namespace ioc.IService
{
    public class SimpleUser : IUser
    {
        public List<UserInfo> GetUsers()
        {
            var list = new List<UserInfo>();
            for (int i = 0; i < 10; i++)
            {
                list.Add(new UserInfo() { ID = i, UserName = "Uer" + i, Age = i });
            }
            return list;
        }
    }
}

1.4、ioc.Model为实体类:这里创建两个实体类(Student,UserInfo)

Student类代码:

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

namespace ioc.Model
{
    public class Student
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Graduation { get; set; }
        public string School { get; set; }
        public string Major { get; set; }
    }
}

 

UserInfo类代码:

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

namespace ioc.Model
{

   public class UserInfo
    {
        public int ID { get; set; }
        public string UserName { get; set; }
        public int Age { get; set; }
    }
}

 

二、基本的数据层和代码准备好之后,我们开始引入容器 Unity:

2.1、右键UI层的引入,点击(管理NuGet程序包),安装这些程序包:

注:或许有些程序包用不到,但我全都引用了(PS:因为本人研究IOC的时候掉了很多坑)

 

2.2、Unity容器的一些程序包引用完成后就进入正题:

1.首先开始编写只用代码不使用配置文件实现IOC:

1)创建 UserController 这个控制类用来测试光用代码实现IOC注入:

UserController 代码部分:

using ioc.IInterFace;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace ioc.Controllers
{
    
    public class UserController : Controller
    {
        private IUser service;
        public UserController(IUser service)
        {
            this.service = service;
        }

        public ActionResult Index()
        {
            var data = this.service.GetUsers();
            return View(data);
        }

    }
}

然后我们在 Global.asax 中初始化 IOC:

Global.asax代码部分:

using ioc.IInterFace;
using ioc.IService;
using ioc.OtherUtil;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using Unity;
using Unity.Mvc5;

namespace ioc
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            //配置文件注入
            //UnityConfig.RegisterComponents(BootStrapper.Init());

            //代码注入Ioc
            var container = this.BuildUnityContainer();
            //这里的UnityDependencyResolver类在测试配置文件注入的时候创建了,所以需要这样区分开
            DependencyResolver.SetResolver(new Unity.Mvc5.UnityDependencyResolver(container));
        }

        /// <summary>
        /// 代码注入ioc方法
        /// </summary>
        /// <returns></returns>
        protected IUnityContainer BuildUnityContainer()
        {
            var container = new UnityContainer();

            container.RegisterType<IUser, SimpleUser>();
            //container.RegisterType<IStudent, SimpleStudent>();

            return container;
        }
    }
}

接下来我们回到 UserController 中 右键Index方法添加视图:

添加完成后是这样的:

User  Index.cshtml 的代码:

@using ioc.Model;

@model List<UserInfo>

@{
    ViewBag.Title = "UserIndex";
}
<h2>Index</h2>
<table class="table">
    <tr>
        <th>ID</th>
        <th>UserName</th>
        <th>Age</th>
    </tr>
    @foreach (var item in Model)
    {
        <tr>
            <td>@item.ID</td>
            <td>@item.UserName</td>
            <td>@item.Age</td>
        </tr>
    }
</table>

然后右键这个Index.cshtml 点击在浏览器中查看(这里使用谷歌浏览器),效果如下:

出现👆👆👆👆👆页面就说明我们的使用代码注入IOC就成功了。

 

2)接下来我们创建 StudentController 这个控制类用来测试使用配置文件实现IOC注入:

StudentController 代码:

using ioc.IInterFace;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace ioc.Controllers
{
    public class StudentController : Controller
    {

         IStudent repository;
        //构造器注入
        public StudentController(IStudent repository)
        {
            this.repository = repository;
        }



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


    }
}

然后还是右键Index方法添加试图,Student视图的Index.cshtml代码为:

@using ioc.Model;
@model List<Student>
@{
    ViewBag.Title = "Index";
}

<table class="table">
    <tr>
        <th>序号</th>
        <th>专业</th>
        <th>姓名</th>
        <th>学校</th>
    </tr>
    @foreach (var item in Model)
    {
<tr>
    <td>@item.Id</td>
    <td>@item.Major</td>
    <td>@item.Name</td>
    <td>@item.School</td>
</tr>
    }
</table>

然后我们新建两个文件夹:OtherConfig 和 OtherUtil

1、在 OtherConfig 文件夹中创建文件:Unity.config;

2、在 OtherUtil 文件夹中创建文件:

BootStrapper:引导类,用于初始化工作;

UnityControllerFactory:继承DefaultControllerFactory,重载GetControllerInstance方法,实现自己的UnityControllerFactory类,并通过IoC容器将之注册为IControllerFactory的实现;

UnityDependencyResolver:实现IDependencyResolver接口并通过DependencyResolver.SetResolver告知MVC,将部分类型实例解析工作交由IoC容器Unity来处理;

如图:

Unity.config 配置文件的代码:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
	<!--unity配置文件-->
	<configSections>
		<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Unity.Configuration" />
	</configSections>

	<unity>
		<containers>
			<container name="IQueryContainer">
				<!--<register type="抽象类,抽象类的命名空间" mapTo="继承这个抽象类的实现类,实现类的命名空间"/>-->
				<register type="ioc.IInterFace.IStudent,ioc.IInterFace" mapTo="ioc.IService.SimpleStudent,ioc.IService"/>
				<!--<register type="ioc.IInterFace.IUser,ioc.IInterFace" mapTo="ioc.IService.SimpleUser,ioc.IService"/>-->
			</container>
		</containers>
	</unity>
	<system.serviceModel>
		<bindings />
		<client />
	</system.serviceModel>
	
</configuration>

 

BootStrapper 类的代码:

using Microsoft.Practices.Unity.Configuration;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Unity;

namespace ioc.OtherUtil
{
    public class BootStrapper
    {
        public static IUnityContainer Init()
        {
            var container = BuildUnityContainer();
            DependencyResolver.SetResolver(new UnityDependencyResolver(container));
            return container;
        }

        private static IUnityContainer BuildUnityContainer()
        {
            var container = new UnityContainer();
            ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
            fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "OtherConfig\\Unity.config");
            Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap,ConfigurationUserLevel.None);
            UnityConfigurationSection section = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);
            section.Configure(container, "IQueryContainer");

            return container;
        }
    }
}

UnityControllerFactory 类的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Unity;

namespace ioc.OtherUtil
{
    /// <summary>
    /// 继承DefaultControllerFactory,重载GetControllerInstance方法,
    /// 实现自己的UnityControllerFactory类,并通过IoC容器将之注册为IControllerFactory的实现
    /// 在配置文件(unity.config)的System.Web.Mvc.IControllerFactory后的mapTo后注册
    /// </summary>
    public class UnityControllerFactory : DefaultControllerFactory
    {
        IUnityContainer container;
        public UnityControllerFactory(IUnityContainer container)
        {
            this.container = container;
        }

        protected override IController GetControllerInstance(RequestContext reqContext, Type controllerType)
        {
            return container.Resolve(controllerType) as IController;
        }
    }
}

UnityDependencyResolver 类的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Unity;

namespace ioc.OtherUtil
{
    /// <summary>
    ///  实现IDependencyResolver接口并通过DependencyResolver.SetResolver告知MVC
    ///  ,将部分类型实例解析工作交由IoC容器Unity来处理
    /// </summary>
    public class UnityDependencyResolver : IDependencyResolver
    {
        IUnityContainer container;
        public UnityDependencyResolver(IUnityContainer container)
        {
            this.container = container;
        }

        public object GetService(Type serviceType)
        {
            if (!this.container.IsRegistered(serviceType))
            {
                return null;
            }
            return container.Resolve(serviceType);
        }

        public IEnumerable<object> GetServices(Type serviceType)
        {
            return container.ResolveAll(serviceType);
        }
    }
}

 

接下来我们在UnityConfig.cs类 和 Global.asax 中初始化容器,代码为:

ps:UnityConfig.cs类是引入Unity.Mvc5时自动创建在App_Start文件夹下的。

UnityConfig.cs类代码:

using ioc.OtherUtil;
using System.Web.Mvc;
using Unity;
using Unity.Mvc5;

namespace ioc
{
    public static class UnityConfig
    {
        public static void RegisterComponents(IUnityContainer container)
        {
            //var container = new UnityContainer();

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

            // e.g. container.RegisterType<ITestService, TestService>();
            ControllerBuilder.Current.SetControllerFactory(new UnityControllerFactory(container));
        }
    }
}

Global.asax代码:

using ioc.IInterFace;
using ioc.IService;
using ioc.OtherUtil;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using Unity;
using Unity.Mvc5;

namespace ioc
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            //配置文件注入
            UnityConfig.RegisterComponents(BootStrapper.Init());

            代码注入Ioc
            //var container = this.BuildUnityContainer();
            这里的UnityDependencyResolver类在测试配置文件注入的时候创建了,所以需要这样区分开
            //DependencyResolver.SetResolver(new Unity.Mvc5.UnityDependencyResolver(container));
        }

        /// <summary>
        /// 代码注入ioc方法
        /// </summary>
        /// <returns></returns>
        //protected IUnityContainer BuildUnityContainer()
        //{
        //    var container = new UnityContainer();

        //    container.RegisterType<IUser, SimpleUser>();
        //    //container.RegisterType<IStudent, SimpleStudent>();

        //    return container;
        //}

    }
}

 

最后我们右键Student下的Index.cshtml点击在浏览器中查看,这是运行结果

这样,两种实现IOC的方式就全部完成了,嘎嘎嘎!!!

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

灿烂GG

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值