Unity使用繼承於 LifetimeManager 基類的類去控制怎樣存放到對象執行個體的引用和容器怎樣銷毀這些執行個體,也就是說Unity基於具體的Lifetime Manager 類去管理對象的建立和銷毀。
目前Unity中提供兩個Lifetime Manager類可供我們直接使用,當然你也可以實現自己的Lifetime Manager類。
1. ContainerControlledLifetimeManager
Unity儲存一個指向對象執行個體的引用。通過Unity容器為同一個類型或對象擷取對象執行個體時,每次擷取到的都是同一個執行個體。也就是說實現了對象單例模式。預設情況下,RegisterInstance方法使用該Lifetime Manager。
2. ExternallyControlledLifetimeManager
Unity僅儲存一個指向對象執行個體的弱引用。通過Unity容器為同一個類型或對象擷取對象執行個體時,每次擷取到的都是同一個執行個體。但是由於當對象建立完之後,容器沒有對該對象的強引用,所以就可能出現當其他地方沒有去強引用它時候,會被GC回收掉。
先看看一個介面和類,下面會用到
public interface IPlayer
{
void Play();
}
public class Mp3Player : IPlayer
{
public void Play()
{
Console.WriteLine("Playing Mp3");
}
}
接下來通過在RegisterType和RegisterInstance時指定相應的Lifetime Manager來介紹Lifetime Manager的應用情境。
1. RegisterType
當用RegisterType註冊映射關係時,如果沒有指定LifetimeManager,預設是使用一個瞬態的Lifetime Manager。即每次通過Unity容器擷取對象的執行個體時都會重新建立一個該執行個體,也就是說Unity容器不存在一個到該對象的引用。
看一個例子:
IUnityContainer container = new UnityContainer();
container.RegisterType<IPlayer, Mp3Player>();
IPlayer player1 = container.Resolve<IPlayer>();
Console.WriteLine(string.Format("Player1 HashCode: {0}",player1.GetHashCode()));
IPlayer player2 = container.Resolve<IPlayer>();
Console.WriteLine(string.Format("Player2 HashCode: {0}",player2.GetHashCode()));
輸出結果:
通過輸出的player1和player2對象的HashCode值可以看出,player1和player2分別是Mp3Player類的不同執行個體。
那怎樣實現單例模式呢?
要實現單例模式,容器需要儲存一個指向對象執行個體的引用。通過在RegisterType時為它指定相應的Lifetime Manager可以實現單例模式,從上面對ContainerControlledLifetimeManager和ExternallyControlledLifetimeManager的介紹可以知道,這兩個Lifetime Manager都可以支援單例模式。
修改上面的代碼為:
IUnityContainer container = new UnityContainer();
//這裡指定使用ContainerControlledLifetimeManager對象
container.RegisterType<IPlayer, Mp3Player>(new ContainerControlledLifetimeManager());
IPlayer player1 = container.Resolve<IPlayer>();
Console.WriteLine(string.Format("Player1 HashCode: {0}",player1.GetHashCode()));
IPlayer player2 = container.Resolve<IPlayer>();
Console.WriteLine(string.Format("Player2 HashCode: {0}",player2.GetHashCode()));
看看輸出:
通過輸出結果可以看出,player1和player2對象為Mp3Player類的同一執行個體,指向同一記憶體位址。
2. RegisterInstance
當用RegisterInstance註冊映射關係時,如果沒有指定Lifetime Manager,預設是使用ContainerControlledLifetimeManager,即支援單例模式。
看個例子:
IUnityContainer container = new UnityContainer();
IPlayer mp3Player = new Mp3Player();
container.RegisterInstance<IPlayer>(mp3Player);
IPlayer player1 = container.Resolve<IPlayer>();
Console.WriteLine(string.Format("Player1 HashCode: {0}", player1.GetHashCode()));
IPlayer player2 = container.Resolve<IPlayer>();
Console.WriteLine(string.Format("Player2 HashCode: {0}", player2.GetHashCode()));
看看輸出:
通過輸出結果可以看出,player1和player2對象為Mp3Player類的同一執行個體,指向同一記憶體位址。
作者:Inrie (洪曉軍)
出處:http://www.cnblogs.com/inrie