代码改变世界

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)