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);
}
}
}
接下來我們在 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的方式就全部完成了,嘎嘎嘎!!!
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/287365.html
標籤:其他
上一篇:Web服務器群集——LVS-DR+Keepalived高可用集群
下一篇:圖解 RabbitMQ 核心概念
