简介:

   控制反转:我们向IOC容器发出获取一个对象实例的一个请求,IOC容器便把这个对象实例“注入”到我们的手中,在这个过程中你不是一个控制者而是一个请求者,依赖于容器提供给你的资源,控制权落到了容器身上。这个过程就是控制反转。 

    依赖注入:我们向容器发出请求以后,获得这个对象实例的过程就叫依赖注入。

   关于Ioc的框架有很多,比如astle Windsor、Unity、Spring.NET、StructureMap,我们这边使用微软提供的Unity做示例,你可以使用 Nuget 添加 Unity ,也可以引用Microsoft.Practices.Unity.dll和Microsoft.Practices.Unity.Configuration.dll,下面我们就一步一步的学习下 Unity依赖注入 的详细使用。

一、使用 Nuget 添加 Unity

二、实现构造注入

添加一个接口和一个实现类,通过Main()方法调用测试。

    /// <summary>
/// 显示信息
/// </summary>
public interface IUserDao
{
void Display(string mes);
} class UserImpl : IUserService
{
public IUserDao IUserDao;
//构造函数设置值
public UserImpl(IUserDao UserDao)
{
IUserDao = UserDao;
}
/// <summary>
/// 显示信息
/// </summary>
/// <param name="mes"></param>
public void Display(string mes)
{
IUserDao.Display(mes);
}
}
 
    /// <summary>
/// 显示信息
/// </summary>
public interface IUserDao
{
void Display(string mes);
} public class UserDaoImpl : IUserDao
{
public void Display(string mes)
{
Console.WriteLine(mes);
}
}
 
class Program
{
public IUserService IUserService { get; set; } public static void Main(string[] args)
{
//创建容器
UnityContainer container = new UnityContainer();
//注册依赖对象
container.RegisterType<IUserService, UserImpl>();
container.RegisterType<IUserDao, UserDaoImpl>();
//返回调用者
IUserService IUser = container.Resolve<UserImpl>();
//执行
IUser.Display("asb");
Console.ReadLine();
}
}

点击运行,成功输出。

构造器注入
构造器注入(Constructor Injection):IoC容器会智能地选择选择和调用适合的构造函数以创建依赖的对象。
如果被选择的构造函数具有相应的参数,IoC容器在调用构造函数之前解析注册的依赖关系并自行获得相应参数对象。
RegisterType:可以看做是自来水厂决定用什么作为水源,可以是水库或是地下水,我只要“注册”开关一下就行了。
Resolve:可以看做是自来水厂要输送水的对象,可以是农村或是城市,我只要“控制”输出就行了。

三、属性注入

属性注入(Property Injection),就是通过 set 设值对对象进行设值,只需要在调用对象的上面加上 [Dependency] 标记即可。当依赖对象被容器初始化以后,会自动对该对象设值。

class UserImpl : IUserService
{
//只需要在对象成员前面加上[Dependency],
//就是把构造函数去掉,成员对象上面加[Dependency]注入
[Dependency]
public IUserDao IUserDao { get; set; } //public UserImpl(IUserDao UserDao)
//{
// IUserDao = UserDao;
//}
/// <summary>
/// 显示信息
/// </summary>
/// <param name="mes"></param>
public void Display(string mes)
{
IUserDao.Display(mes);
}
}

点击运行,实现的结果是一样的。

配置文件注册:

  其实使用上面 RegisterType 方法进行注册,每次添加和删除一个注册都需要去修改代码和重新编译,这样不符合“高内聚、低耦合”的编程思想,所以我们可以采用配置文件的方式去注册,这样每次添加和修改注册就不需要去修改代码和重新发布了。配置文件注册用 UnityConfigurationSection 的 Configure加载配置文件注册。

代码(如果是控制台程序,配置写在App.config,如果是Web程序,就写在 Web.config):

<?xml version="1.0" encoding="utf-8" ?>
<configuration> <configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
Microsoft.Practices.Unity.Configuration" />
</configSections>
<unity xmlns="http://schemas.microsoft.com/practces/2010/unity">
<containers>
<!--MyContainer为自定义名称 只需要和调用时名称保持一致即可-->
<container name="MyContainer">
<!--type为对象的名称,mapTo为注入对象的名称 写法为用逗号隔开两部分,一是类的全部,包括命名空间,二是程序集名称-->
<register type="ThreadDemo.Bll.IUserBll,ThreadDemo" mapTo="ThreadDemo.Bll.impl.UserBll,ThreadDemo">
<lifetime type="singleton" />
</register>
<register type="ThreadDemo.Dal.IUserDal,ThreadDemo" mapTo="ThreadDemo.Dal.impl.UserDal,ThreadDemo"/>
</container>
</containers>
</unity>
<!--startup必须放在<configSections>节点下面,否则报错-->
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
</configuration>
 
class Program
{
public IUserBll UserBll { get; set; } public static void Main(string[] args)
{
//创建容器
//UnityContainer container = new UnityContainer();
//注册依赖对象
//container.RegisterType<IUserService, UserImpl>();
//container.RegisterType<IUserDao, UserDaoImpl>();
//返回调用者
//IUserService IUser = container.Resolve<UserImpl>(); //创建容器
UnityContainer container = new UnityContainer();
UnityConfigurationSection config = (UnityConfigurationSection)ConfigurationManager.GetSection(UnityConfigurationSection.SectionName);
//加载到容器
config.Configure(container, "MyContainer"); //返回调用者
IUserBll IUser = container.Resolve<IUserBll>();
//执行
IUser.Display("abc");
Console.ReadLine();
}
}

四、方法注入

  方法注入和构造注入差不多,只不过把构造函数变成了一个普通的方法,在方法前面加  [InjectionMethod]  属性。

namespace ThreadDemo.Bll.impl
{
public class UserBll : IUserBll
{
public IUserDal IDal; /// <summary>
/// 方法注入-加[InjectionMethod]属性
/// </summary>
/// <param name="IUserDal"></param>
[InjectionMethod]
public void SetInjection(IUserDal IUserDal)
{
IDal = IUserDal;
} /// <summary>
/// 显示信息
/// </summary>
/// <param name="mes"></param>
public void Display(string mes)
{
IDal.Display(mes);
}
}
}

这几种方法运行结果都是一样的。

五、Unity.MVC在Web中的应用

下面的例子是在Unity在Web项目中的使用:

1、安装Unity.MVC

2、在目录下会生成一个 BootStrapper.cs  的类文件,打开进行 编辑(如果没有生成,自己创建,名称随意)。

namespace ShowWeatherWebUI
{
public class BootStrapper
{
/// <summary>
/// 获取容器-注册依赖关系
/// </summary>
/// <returns></returns>
public static IUnityContainer Initialise()
{
var container = BuildUnityContainer(); DependencyResolver.SetResolver(new UnityDependencyResolver(container)); return container;
} /// <summary>
/// 加载容器
/// </summary>
/// <returns></returns>
private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer(); RegisterTypes(container); return container;
} /// <summary>
/// 实施依赖注入
/// </summary>
/// <param name="container"></param>
private static void RegisterTypes(UnityContainer container)
{
//依赖关系可以选择代码形式,也可以用配置文件的形式
//UnityConfigurationSection config = (UnityConfigurationSection)ConfigurationManager.GetSection(UnityConfigurationSection.SectionName);
//加载到容器
//config.Configure(container, "MyContainer"); container.RegisterType<IUerBll, UerBll>();
container.RegisterType<IUserDal, UserDal>();
}
}
}

3、在 Global.asax 文件中添加 BootStrapper.Initialise() 的方法。

  因为Global.asax是应用程序启动的时候会执行,所以会去加载容器

public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
//加载容器-注册依赖
BootStrapper.Initialise();
}
}

4、在Controller里调用,

在每个调用的接口添加 [Dependency] 属性即可,也就是属性输入,也可以采用构造函数注入和方法注入。

 public class HomeController : Controller
{
[Dependency]
public IUerBll bll { get; set; } public ActionResult Index()
{
bll.Display("asd");
return View();
}
}

代码下载

C# Unity依赖注入的更多相关文章

  1. Unity 依赖注入之二

    1. 构造子注入 1.1 构造子注入初级代码 container.RegisterType<IMyWork, MyWork>(new InjectionConstructor(new Bo ...

  2. Unity依赖注入使用详解

    写在前面 构造器注入 Dependency属性注入 InjectionMethod方法注入 非泛型注入 标识键 ContainerControlledLifetimeManager单例 Unity注册 ...

  3. WPF PRISM开发入门二(Unity依赖注入容器使用)

    这篇博客将通过一个控制台程序简单了解下PRISM下Unity依赖注入容器的使用.我已经创建了一个例子,通过一个控制台程序进行加减乘除运算,项目当中将输入输出等都用接口封装后,结构如下: 当前代码可以点 ...

  4. Unity 依赖注入

    关于Ioc的框架有很多,比如astle Windsor.Unity.Spring.NET.StructureMap,我们这边使用微软提供的Unity做示例,你可以使用Nuget添加Unity,也可以引 ...

  5. c# Unity依赖注入WebService

    1.IOC与DI简介 IOC全称是Inversion Of Control(控制反转),不是一种技术,只是一种思想,一个重要的面相对象编程的法则,它能知道我们如何设计出松耦合,更优良的程序.传统应用程 ...

  6. 使用Microsoft.Practices.Unity 依赖注入

    Unity是微软Patterns & Practices团队所开发的一个轻量级的,并且可扩展的依赖注入(Dependency Injection)容器,它支持常用的三种依赖注入方式:构造器注入 ...

  7. 使用Microsoft.Practices.Unity 依赖注入 转载https://www.cnblogs.com/slardar1978/p/4205394.html

    Unity是微软Patterns & Practices团队所开发的一个轻量级的,并且可扩展的依赖注入(Dependency Injection)容器,它支持常用的三种依赖注入方式:构造器注入 ...

  8. ASP.NET MVC5+EF6+EasyUI 后台管理系统(6)-Unity 依赖注入

    系列目录 前言 为了符合后面更新后的重构系统,文章于2016-11-1日重写 本节重构一下代码,采用IOC控制反转,也就是依赖注入 您可以访问http://unity.codeplex.com/rel ...

  9. Unity 依赖注入知识点

    三种依赖注入方法,构造器注入.属性注入.方法注入 可以配置Config文件,来实现不用修改代码.需要先将接口与实体关联,然后使用时会自动加载对应实体. namespace WeChatConsole ...

随机推荐

  1. 2018-2019-1 20189201《Linux内核原理与分析》第四周作业

    1. 阴天☁️ 你说你爱烟雨微茫,雨来时你却伞遮霓裳: 你说你爱春光灿烂,阳光普照时你却孑然惆怅: 你说你爱微风轻柔,风拂发梢时你却紧闭门窗: 这便是为何你说你也深深爱我,我却眼波成霜. 2. 今日发 ...

  2. sqlalchemy.exc.ProgrammingError: (pymysql.err.ProgrammingError)

    在我学习flask建立网站时间碰到了一个棘手的问题,就是在我进行操作日志的更新时间,发现表格建立有点错误,导致表缺失,从而报了下面的错误 sqlalchemy.exc.ProgrammingError ...

  3. less那些事儿

    1.计算函数 less写法要特殊处理一下,否则会被识别成calc(60%); /* css */ width: calc(100% - 40px); / * less */ width : calc( ...

  4. 网络流之最大流Dinic算法模版

    /* 网络流之最大流Dinic算法模版 */ #include <cstring> #include <cstdio> #include <queue> using ...

  5. Docker操作笔记(四)使用网络

    使用网络 Docker允许通过外部访问容器或容器互联的方式来提供网络服务. 一.外部访问容器 容器中可以运行一些网络应用,要让外部也可以访问这些应用,可以通过 -P 或 -p 参数来指定端口映射. 当 ...

  6. Mysql5.7 单表 500万数据迁移到新表的快速实现方案

    开发过程中需要把一个已有500万条记录的表数据同步到另一个新表中,刚好体验下Mysql官方推荐的大数据迁移的方案:SELECT INTO OUTFILE,LOAD DATA INFILE Mysql ...

  7. 07-Python入门学习-字符编码与文件处理

    字符编码 人操作计算机使用人类认识的字符,而计算机存放都是二进制数字所以人在往计算机里输入内容的时候,必然发生: 人类的字符------(字符编码表)-------->数字 比如我输入一个‘上’ ...

  8. Chapter 2 Basic Elements of JAVA

    elaborate:详细说明 Data TypesJava categorizes data into different types, and only certain operationscan ...

  9. Fliptile [POJ3279] [开关问题]

    题意 给定一张n*m的方格图,有1,0两种数字,每次可以选取一个十字进行翻转,1变成0,0变成1,问最少需要翻转几次,使它全部变成0,全部如果有重复的,按字典序最小的进行输出: 输入 第一行n,m 下 ...

  10. Java Web 禁用Cookie对Session的影响

    如果客户端禁用了Cookie,那么服务端就不能得到Session了.因为通过Session ID来确定当前会话对应的服务端Session,而Session ID通过Cookie来传递,所以禁用Cook ...