IOC注入框架——Unity初步
2012-10-27 21:19 C#与.NET探索者 阅读(790) 评论(0) 编辑 收藏 举报Unity 应用程序块(Unity)是一个轻量级、可扩展的依赖注入容器,支持构造函数、属性和方法调用注入。它有下列优点:
1、简化了对象的创建,尤其是分层的对象结构和依赖,并简化了应用程序代码。
2、支持需求的抽象,这允许开发人员在运行时或者配置中指定依赖,并简化了横切关注点的管理。
3、通过延迟将配置组装到容器来提高灵活性。
4、服务定位功能允许客户代码保存或者缓存容器。这在开发人员可以持久化容器到 ASP.NET Session 或者 Application 中的 ASP.NET Web 应用程序中特别有用。
依赖注入:这是 Ioc 模式的一种特殊情况,是一种基于改变对象的行为而不改变类的内部的接口编程技术。开发人员编写实现接口的类代码,并基于接口或者对象类型使用容器注入依赖的对象实例到类中。用于注入对象实例的技术是接口注入、构造函数注入、属性(设置器)注入和方法调用注入。
准备工作:
1、安装Unity Application Block 1.1.msi
2、创建新网站
3、添加Microsoft.Practices.Unity.Configuration.dll、Microsoft.Practices.Unity.dll、Microsoft.Practices.ObjectBuilder2.dll三个文件的引用
4、创建一个新的类文件(.cs),并导入命名空间
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;
5、在此类文件中建立如下几个类
//抽象类,播放器
public abstract class Player
{
public abstract string Play(); //播放功能
}
//MP3播放器
public class MP3Player : Player
{
public override string Play()
{
return "this is MP3Player";
}
}
//CD播放器
public class CDPlayer : Player
{
public override string Play()
{
return "this is CDPlayer";
}
}
//DVD播放器
public class DVDPlayer : Player
{
public override string Play()
{
return "this is DVDPlayer";
}
}
一、创建容器
IUnityContainer container = new UnityContainer();
该容器的作是用管理抽象类型与对应具体类型的工具,所以它是我们Unity中实现依赖注入的必备对象
二、在容器中注册抽象类型 与具体类型的映射关系。有两种注册方式。
1. RegisterType:在容器中注册“接口”( 包括 Interface 和 Base Class ) 到“具体类”的映射。
container.RegisterType<IPlayer, Mp3Player>();//注册IPlay接口映射为Mp3Player类
一个接口可能会映射多个具体类,可以为每个映射指定Name,如:
container.RegisterType<IPlayer, Mp3Player>("myMp3Player1");
container.RegisterType<IPlayer, CDPlayer>("myCDPlayer1");
RegisterType有以下几个重载方法:
RegisterType<TFrom, TTo>( )
RegisterType<TFrom, TTo>(LifetimeManager lifetime)
RegisterType<TFrom, TTo>(String name)
RegisterType<TFrom, TTo>(String name, LifetimeManager lifetime)
RegisterType<T>(LifetimeManager lifetime)
RegisterType<T>(String name, LifetimeManager lifetime)
2. RegisterInstance:在容器中注册“接口”( 包括 Interface 和 Base Class ) 到“实例”的映射。
Mp3Player mp3Player = new Mp3Player();
container.RegisterInstance<IPlayer>(mp3Player);//注册IPlayer接口映射为mp3Player实例
同样的也可以为该映射指定Name,如:
container.RegisterInstance<IPlayer>("myMp3Player", mp3Player);
RegisterInstance有以下几个重载方法:
RegisterInstance<TInterface>(TInterface instance)
RegisterInstance<TInterface>(TInterface instance, LifetimeManager lifetime)
RegisterInstance<TInterface>(String name, TInterface instance)
RegisterInstance<TInterface>(String name, TInterface instance, LifetimeManager lifetime)
三、根据容器中注册的映射关系,来动态取得对象实例
IUnityContainer container = new UnityContainer();
container.RegisterType<IPlayer, Mp3Player>();
IPlayer player = container.Resolve<IPlayer>();//通过Resolve方法获取IPlayer接口所映射的Mp3Player的实例。
如果IPlayer接口注册两个映射类:Mp3Player和CDPlayer。通过Resolve方法获取到的这个player对象将获取的是最后注册的具体类型的对象。
IUnityContainer container = new UnityContainer();
container.RegisterType<IPlayer, Mp3Player>();
container.RegisterType<IPlayer, CDPlayer>();
IPlayer player = container.Resolve<IPlayer>();
player.Play(); //此时调用的方法是CDPlayer对象的Play方法。
Unity中当遇到一个接口映射到多个具体类情况时,Resolve时候使用最后注册的映射。如果获得指定的具体类的对象,应当在容器中注册的时候为每个注册起个名子,并在解析(Resolve)是指定要解析的名子。
IUnityContainer container = new UnityContainer();
container.RegisterType<IPlayer, Mp3Player>("myMp3Player1");
container.RegisterType<IPlayer, CDPlayer>("myCDPlayer1");
IPlayer player = container.Resolve<IPlayer>("myMp3Player1");
palyer.Play(); ////此时调用的方法是MP3Player对象的Play方法。
可以看出Resolve方法可以通过指定Name( 这个Name值对应着RegisterType时指定的Name值 ),通过这种方式可以获取到指定的对象实例。所以当一个接口映射到多个具体类时,还是很有必要为这些映射指定Name。
注意:RegisterType<TFrom,TTO>(string name)和Resolve<T>(string name)方法中的name值为大小写敏感的。
Resolve的重载方法:
Resolve<T>( )
Resolve<T>(string name)
Resolve(Type t)
Resolve(Type t, string name)
四、获取所有对象实例
可以通过ResolveAll方法来获取指定接口的所有对象实例:
ResolveAll方法返回的IEnumerable类型的对象,可以使用foreach进行迭代
IUnityContainer container = new UnityContainer();
container.RegisterType<IPlayer, Mp3Player>("myMP3Player");
container.RegisterType<IPlayer, CDPlayer>("myCDPlayer");
container.RegisterType<IPlayer, DVDPlayer>();
IEnumerable<IPlayer> players = container.ResolveAll<IPlayer>();
foreach (IPlayer player in players)
{
player.Play();
}
ResolveAll有以下两个重载方法:
ResolveAll<T>( )
ResolveAll(Type t)