malaikuangren

What is the purpose or drive to build thing like (xxx),How can it achieve the original goal of design?
Unity用法(属性注入的两种方法)

 对象之间的依赖关系有时还表现为通过属性来引入的方式,同样也可以用IOC的Property (Setter) Injection 方式来解耦。

 

什么情况下使用Property (Setter) Injection


当实例化父对象时也能自动实例化所依赖的对象
通过简单的方式使得很容易做到在代码中查看每个类所依赖的项
父对象有很多相互之间有关联关系的构造器,导致在调试和维护时很不方便。
父对象包含有很多参数构造器,特别是参数类型相似的只能通过参数的位置来辨别的
让用户(将调用这些代码的程序)更方便的看到有哪些对象可以用,这在Constructor Injection里是没办法实现的。

通过修改依赖对象的代码来控制哪些对象可以被注入,而不用改动父对象或应用程序 

 

配置文件方式:

现假设有如下对象

public class WmaPlayer : IPlayer
    {
        public void Play()
        {
            this.WmaSong.Name = "xxx";
            this.WmaSong.Singer = "yyy";
            Console.WriteLine(string.Format("Now Playing [{0}] Singing by ({1})", this.WmaSong.Name, this.WmaSong.Singer));
        }
        public Song WmaSong
        {
            get;
            set;
        }

    } 

 

在配置文件中添加如下配置

<register  type="IPlayer"
                mapTo="SongPlayerLib.WmaPlayer,
                SongPlayerLib" name="WmaPlayer">
          <property name="WmaSong"  dependencyType="Song"/>

        </register > 

其中dependencyType="Song" 的Song可以在

<typeAlias alias="Song"
          type="SongPlayerLib.Song,

          SongPlayerLib" /> 中配置别名。

如果对同一个IPlayer接口的map有多个配置 。

如:

<register  type="IPlayer"
                mapTo="SongPlayerLib.Mp3Player,

                SongPlayerLib"> 

那么可以通过以下方式来得到对应的类型实例

IPlayer player = container.Resolve<IPlayer>("WmaPlayer"); 

这样就得到是WmaPlayer实例。 

 

代码方式:

假设有如下类定义:

 

//歌曲类
public class Song
{
    //歌手
    
public string Singer
    {
        
get
        {
            
return "Westlife";
        }
    }

    //歌曲名
    
public string Name
    {
        
get
        {
            
return "My Love";
        }
    }
}


public
 abstract class Player
{
    [Dependency]
    
public Song Song { getset; }

    
public abstract string Name { get; }

    
public void Play()
    {
        Console.WriteLine(
string.Format("{0}: Now Playing [{1}] Singing by ({2})"this.Name, this.Song.Name, this.Song.Singer));
    }
}

public class Mp3Player : Player
{
    
public override string Name
    {
        
get
        {
            
return "Mp3 Player";
        }
    }
}

public class CDPlayer : Player
{
    
public override string Name
    {
        
get
        {
            
return "CD Player";
        }
    }
}

开始

通过为类的属性贴上[Dependency]标签,使得Unity容器在获取类对象实例时,自动实例化该属性所依赖的对象,并注入到属性中。

看一个例子,Mp3Player类有一个Song属性,它被贴上[Dependency]标签。

[Dependency]
public Song Song { getset; }

可以通过下面的方式来获取Mp3Player对象实例:

IUnityContainer container = new UnityContainer();
container.RegisterType
<Player, Mp3Player>();

Player player 
= container.Resolve<Player>();

player.Play(); 

这里通过为Mp3Player类的Song属性贴上[Dependency]标签,来表示Unity容器装载对象时将自动实例化Song对象,然后注入到Mp3Player的Song属性里。

从输出结果可以看出,容器在装配Mp3Player对象时自动装载有加上[Dependency]标签的所依赖的属性对象。


还可以为[Dependency]特性指定Name,再看一个例子:

这是一个播放器商店类,为PopularPlayer属性贴上[Dependency]标签,同时指定Name为"Mp3Player"。

//播放器商店
public
 class PlayerStore
{
    
//最受欢迎的播放器类型(Mp3Player、CDPlayer)
    [Dependency("Mp3Player")]
    
public Player PopularPlayer { getset; }
}

在Unity容器中为Player基类注册两个映射( Mp3Player 和 CDPlayer ), 分别指定映射的Name。可以通过下面的方式来获取PlayerStore对象实例,并输出该店最受欢迎的播放器名:

IUnityContainer container = new UnityContainer();
container.RegisterType
<Player, Mp3Player>("Mp3Player");
container.RegisterType
<Player, CDPlayer>("CDPlayer");

PlayerStore player 
= container.Resolve<PlayerStore>();

Console.WriteLine(player.PopularPlayer.Name); 

 

由于Player映射到Mp3Player和CDPlayer中,通过为[Dependency] Attribute指定Name可以达到匹配对应的具体Player类的目的。 

 

posted on 2012-05-20 21:56  malaikuangren  阅读(1187)  评论(0编辑  收藏  举报