Unity轻量级依赖注入容器
一、前言
Unity是一个轻量级的可扩展的依赖注入容器,支持构造函数,属性和方法调用注入。在Nuget里安装unity
二、Unity的API方法
UnityContainer.RegisterType<ITFrom,TTO>(); //注册映射
UnityContainer.RegisterType< ITFrom, TTO >("keyName");//注册映射指定key值
IEnumerable<T> databases = UnityContainer.ResolveAll<T>(); //返回所有注册同一个接口的实例对象
IT instance = UnityContainer.Resolve<IT>(); //返回最后一个注册同一个接口的实例对象,每次都是创建新的对象
T instance = UnityContainer.Resolve<T>("keyName");//根据key值获取指定的实例对象,每次都是创建新的对象
UnitContainer.RegisterInstance<T>("keyName",new T()); //单例模式,指定key值,获取同一个实例对象
UnityContainer.BuildUp(existingInstance);
IUnityContainer childContainer1 = parentContainer.CreateChildContainer();
三、示例代码
1.演示的是container.Resolve<T>()创建T类型,而T是否已经注册过了,没注册过的就会尝试去创建T类型,在创建T类型的构造函数时,如果需要传递参数,也要涉及到参数是否注册过的问题
定义日志接口
public interface ILogger
{
void Write(string log);
}
public class FileLogger:ILogger
{
public void Write(string log)
{
Console.WriteLine("输出日志到文件!");
}
}
public class ConsoleLogger : ILogger
{
public void Write(string log)
{
Console.WriteLine("输出日志到控制台!");
}
}
定义数据库类
public class Database
{
}
public class CustomerDatabase : Database
{
private ILogger _logger;
public CustomerDatabase(ILogger logger)
{
_logger = logger;
}
public void Write(string log) { _logger.Write(log); }
}
static void Main(string[] args)
{
//实例化Unity容器
UnityContainer container = new UnityContainer();
//注册类型映射
container.RegisterType<ILogger, FileLogger>();
container.RegisterType<ILogger, ConsoleLogger>();
//使用Resolve方法创建我们定义好的CustomerDatabase类型,如果在容器中没有注册的类型。执行Resolv方法后,Unity尝试创建该类型,会执行该类的构造器
// public CustomerDatabase(ILogger logger)的构造函数需要传递一个日志接口实例,它默认传递上面最后注册的ConsoleLogger实例
CustomerDatabase database = container.Resolve<CustomerDatabase>();
database.Write("qqq");
Console.ReadKey();
}
2.演示的是创建注册过的实例,并且返回的是新对象
static void Main(string[] args)
{
UnityContainer container = new UnityContainer();
container.RegisterType<ILogger, FileLogger>();
ILogger logger = container.Resolve<ILogger>();
ILogger logger2 = container.Resolve<ILogger>();
Console.WriteLine(object.ReferenceEquals(logger,logger2));
Console.ReadKey();
}
输出的是false,是不同的对象,说明每次调用container.Resolve<ILogger>()返回的是新的FileLogger对象
3.演示的是每次返回的都是同一个对象,不要例如2创建不同的对象,就像单例模式,RegisterType方法包含一个重载,将使用 new ContainerControlledLifetimeManager()
static void Main(string[] args)
{
UnityContainer container = new UnityContainer();
container.RegisterType<ILogger, FileLogger>();
container.RegisterType<Database, CustomerDatabase> (new ContainerControlledLifetimeManager());
CustomerDatabase bs1 = container.Resolve<CustomerDatabase>();
CustomerDatabase bs2 = container.Resolve<CustomerDatabase>();
Console.WriteLine(object.ReferenceEquals(bs1, bs2));
Console.ReadKey();
}
4.如果类似例子1,注册同一个接口的不同实例 ,使用 container.Resolve<ILogger>();只是返回最后一个注册的ConsoleLogger实例,改进在我们向容器里注册时,可以附带一个string 类型的Key值。可以使用key值获取指定的实例对象
//注册类型映射,同一个接口的不同实例
container.RegisterType<ILogger, FileLogger>();
container.RegisterType<ILogger, ConsoleLogger>(); 使用 container.Resolve<ILogger>();只是返回最后一个注册的ConsoleLogger实例 ILogger logger2 = container.Resolve<ILogger>();改进如下:再创建两个数据库类
public class SQLDatabase:Database
{
}
public class ORACLEDatabase:Database
{
}
使用key获取指定的数据库实例对象
static void Main(string[] args)
{
UnityContainer container = new UnityContainer();
container.RegisterType<Database, SQLDatabase>("SQL");
container.RegisterType<Database, ORACLEDatabase>("ORACLE");
//返回所有的实例
IEnumerable<Database> databases = container.ResolveAll<Database>();
//根据key返回指定的SQL数据库实例
Database database = container.Resolve<Database>("SQL");
}
5.使用RegisterInstance注册传入的实例,后面再调用Resolve就会像例子3一样返回同一个实例对象
static void Main(string[] args)
{
UnityContainer container = new UnityContainer();
container.RegisterInstance<Database>(new SQLDatabase());
container.RegisterInstance<Database>("Oracle", new ORACLEDatabase());
Database database1 = container.Resolve<Database>();
Database database2 = container.Resolve<Database>();
Database oracleDatabase = container.Resolve<Database>("Oracle");
Console.WriteLine(object.ReferenceEquals(database1, database2));
Console.ReadKey();
}
5.1我们还有一种方法可以把已经存在的实例注入到容器中,这里用到了BuildUp和RegisterInstance,其实我觉得用不用BuildUp都可以了
public class DB2Database:Database
{
[Dependency]
public ILogger Logger { get; set; }
}
static void Main(string[] args)
{
UnityContainer container = new UnityContainer();
container.RegisterType<ILogger, FileLogger>();
DB2Database existDatabase = new DB2Database();
container.BuildUp(existDatabase);
container.RegisterInstance<Database>(existDatabase);
//DB2Database的属性中Logger上面打了 [Dependency]特性,所以根据这里RegisterType<ILogger, FileLogger>();会默认给DB2Database的Logger属性注入FileLogger
Database database1 = container.Resolve<Database>();
Database database2 = container.Resolve<Database>();
Console.WriteLine(object.ReferenceEquals(database1, database2));
Console.ReadKey();
}
四、使用配置文件来实现关系映射
1.配置如下
<configuration>
<configSections>
<section name="unity"
type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
Microsoft.Practices.Unity.Configuration"/>
</configSections>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<container name="containerOne">
<types>
<type type="UnityDemo.ILogger" mapTo="UnityDemo.FileLogger"
lifeTime="Singleton"/>
</types>
</container>
</unity>
</configuration>
2.读取配置文件
第一种,我们使用configurationManager,引用命名空间System.Configuration
IUnityContainer myContainer = new UnityContainer();
myContainer.LoadConfiguration("containerOne ");
UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
section.Configure(myContainer, "containerOne");
第二种,我们可以直接用容器读取配置信息
IUnityContainer myContainer = new UnityContainer();
myContainer.LoadConfiguration("containerOne");
通过 Injection API 指定依赖
public class GenericDatabase:Database
{
private string _connectionString;
public ILogger Logger { get; set; }
public GenericDatabase(string connectionString)
{
_connectionString = connectionString;
}
}
通过Injection API 来为这个类注入connectionString 和 Logger,首先我们要注册映射关系:
IUnityContainer container = new UnityContainer();
container.RegisterType<ILogger, FileLogger>();
container.RegisterType<Database, GenericDatabase>();
然后通过Injection API 为GenericDatabase注入ConnectionStrings和Logger
container.Configure<InjectedMembers>()
.ConfigureInjectionFor<GenericDatabase>(
new InjectionConstructor(
ConfigurationManager.ConnectionStrings["ConnectionStrings"] == null
? "defaultConnectionString" : ConfigurationManager.ConnectionStrings["ConnectionStrings"].ConnectionString),
new InjectionProperty("Logger")
);
Database database = container.Resolve<Database>();
这样最后获得的database 就包含了connection 和 Logger
嵌套式容器
容器是可以嵌套的,获取实例时遵循的规则是,如果子容器里不包含需要的对象,则会去父容器获取。如果有,则从自己里获取。一旦父容器销毁,子容器也随之销毁。
UnityContainer parentContainer = new UnityContainer();
IUnityContainer childContainer1 = parentContainer.CreateChildContainer();
IUnityContainer childContainer2 = parentContainer.CreateChildContainer();
parentContainer.RegisterType<ILogger, FileLogger>(new ContainerControlledLifetimeManager());
childContainer1.RegisterType<ILogger, ConsoleLogger>(new ContainerControlledLifetimeManager());
//子容器childContainer2里面没有注册日志类型,所以从父parentContainer得到FileLogger
ILogger logger = childContainer2.Resolve<ILogger>();
logger.Write("qqq");
//子容器childContainer1里面有注册控制台日志,所以从自己本身得到consoleLogger
ILogger logger2 = childContainer1.Resolve<ILogger>();
Unity轻量级依赖注入容器的更多相关文章
- IoC 依赖注入容器 Unity
原文:IoC 依赖注入容器 Unity IoC 是什么? 在软件工程领域,“控制反转(Inversion of Control,缩写为IoC)”是一种编程技术,表述在面向对象编程中,可描述为在编译时静 ...
- WPF PRISM开发入门二(Unity依赖注入容器使用)
这篇博客将通过一个控制台程序简单了解下PRISM下Unity依赖注入容器的使用.我已经创建了一个例子,通过一个控制台程序进行加减乘除运算,项目当中将输入输出等都用接口封装后,结构如下: 当前代码可以点 ...
- 不用Unity库,自己实现.NET轻量级依赖注入
在面向对象的设计中,依赖注入(IoC)作为一种重要的设计模式,主要用于削减计算机程序的耦合问题,相对于Java中的Spring框架来说,微软企业库中的Unity框架是目前.NET平台中运用比较广泛的依 ...
- Entity Framework 实体框架的形成之旅--利用Unity对象依赖注入优化实体框架(2)
在本系列的第一篇随笔<Entity Framework 实体框架的形成之旅--基于泛型的仓储模式的实体框架(1)>中介绍了Entity Framework 实体框架的一些基础知识,以及构建 ...
- .NET 使用unity实现依赖注入
原文地址:http://www.cnblogs.com/wujy/p/3317795.html 一:理论部分 依赖注入:这是 Ioc 模式的一种特殊情况,是一种基于改变对象的行为而不改变类的内部的接口 ...
- 运用Unity实现依赖注入[结合简单三层实例]
运用Unity实现依赖注入[结合简单三层实例] 一:理论部分 依赖注入:这是 Ioc 模式的一种特殊情况,是一种基于改变对象的行为而不改变类的内部的接口编程技术.开发人员编写实现接口的类代码,并基于接 ...
- 【ASP.Net MVC3 】使用Unity 实现依赖注入
转载于:http://www.cnblogs.com/techborther/archive/2012/01/06/2313498.html 家人身体不太好,好几天没在园子里发帖了. 新项目还是要用M ...
- Autofac依赖注入容器
依赖注入容器-- Autofac https://github.com/danielpalme/IocPerformance Unity 更新频率高,微软的项目Grace 综合性能更高 目录: 一.简 ...
- 在 mvc 4 中使用 unity 进行依赖注入
在 mvc 4 中使用 unity 进行依赖注入 关于依赖注入的概念,这里就不再叙述了,我们用 mvc 4 结合 unity,使用构造函数来进行依 赖注入.具体步骤如下: 1. 首先建立 一个 mvc ...
随机推荐
- WCF入门教程系列五
一.概述 WCF在通信过程中有三种模式:请求与答复.单向.双工通信.以下我们一一介绍. 二.请求与答复模式 描述: 客户端发送请求,然后一直等待服务端的响应(异步调用除外),期间处于假死状态,直到服务 ...
- C语言中的sizeof和strlen
1.sizeof是算符,strlen是函数: 2.sizeof可以用类型做参数,strlen只能用char*做参数,且必须是以''\0''结尾的: 3.大部分编译程序,在编译的时候就把sizeof计算 ...
- socket网络编程中的同步,异步,阻塞式,非阻塞式,有何联系与区别?
一.举个打电话的例子: 阻塞 block 是指,你拨通某人的电话,但是此人不在,于是你拿着电话等他回来,其间不能再用电话.同步大概和阻塞差不多. 非阻塞 nonblock 是指,你拨通 ...
- c# 中的线程和同步
一.新建线程的3种方法 a)异步委托:b)Thread类:c)线程池: 二.异步委托 1.简单使用,检查委托是否完成其任务 a) 通过 BeginInvoke() 的返回值IAsyncResult ...
- HDU 4268 Alice and Bob set用法
题目地址: http://acm.hdu.edu.cn/showproblem.php?pid=4268 贪心思想,用set实现平衡树,但是set有唯一性,所以要用 multiset AC代码: #i ...
- freemarker中遍历list<map<String,String>>
<#list var as map><tr> <#list map?keys as itemKey> //关键点 <#if itemKey=" ...
- 常用js代码整理、收集
个人整理了一下个人常用到的一些js代码,以方便学习以及日后使用,或许有一些是个人之前从网上摘下来的,但是不记得是具体从哪里来的了,如果你看到有一段代码跟你的文章很相似甚至一样,请不要气愤,请告诉我,我 ...
- 转载:CPU的位数和操作系统的位数
1. 32位系统最大只能使用3.5G的内存,而64位系统最大能够使用128G内存. 2. 32位CPU只能安装和使用32位.16位的系统和软件,无法使用64位系统及软件. 3. 64位可以安装64位系 ...
- 用UseMiddleware扩展方法注册中间件类
用UseMiddleware扩展方法注册中间件类 .NET Core中间件的注册和管道的构建(2)---- 用UseMiddleware扩展方法注册中间件类 0x00 为什么要引入扩展方法 有的中间件 ...
- linux之getcwd函数解析
[lingyun@localhost getcwd]$ cat getcwd.c /********************************************************** ...