初試TinyIoCContainer筆記


第一次看到TinyIoCContainer是在用NancyFx的時候,在Bootstrapper那里看到了她的影子。

那些叫Tiny的東西都挺有意思,IoC容器是我第一次遇到,於是找了些文章看了看,自己寫了點代碼實踐下,這件事就算這么過了,然后今天想起來,在做下筆記。

首先是DIP的概念:依賴倒置原則,OOD的產物。

那么IoC就是DIP的實現方式,用我粗糙的話來說就是類依賴抽象就不在類內部自己new,交給別人new好了再用。

來一個應用場景:

  玩家玩游戲機。

代碼差不多這樣:

 1     interface IGameMachine
 2     {
 3         void Launch();
 4     }
 5 
 6     class Player
 7     {
 8         public IGameMachine GameMachine;
 9 
10         public void Play()
11         {
12        if(GameMachine!=null)
13               GameMachine.Launch();
14         }
15     }
16 
17     class PS3 : IGameMachine
18     {
19         public void Launch()
20         {
21             Console.WriteLine("索尼大法好,PS3開起來啦!");
22         }
23     }

 

這里定義了一個Player類表示玩家,玩家玩的是游戲機,並不指定是什么游戲機,所以有個可以“跑”的游戲機接口,PS3實現了這個接口。那么我就可以在通過賦值更換玩家手上的游戲機來玩PS3了。

1  Player player = new Player();
2  player.GameMachine = new PS3();
3  player.Play();

這樣就實現了上面說的“不在類內部new,交給別人new”這一點。

交給TinyIoCContainer來完成就是這樣:

1  TinyIoCContainer tiny = new TinyIoCContainer();
2  tiny.Register<IGameMachine, PS3>();
3  Player player = new Player
4  {
5    GameMachine = tiny.Resolve<IGameMachine>()
6  };
7  player.Play();

大多數情況下,在項目中遇到的還沒這種可能隨時更換的,而是一旦啟動就不更換的組件,像數據庫之類的,這樣的情況下,這個接口成員就可以不public出來,而是private並且通過構造函數初始化。

還是同樣的應用場景,只是玩家都變得很窮很窮了,一輩子就只能買一台游戲機。改造下Player類之后,我們可以這樣使用TinyIoCContainer了:

    class Player
    {
        private readonly IGameMachine _gameMachine;

        public Player(IGameMachine gameMachine)
        {
            _gameMachine = gameMachine;
        }

        public void Play()
        {
            if (_gameMachine != null)
                _gameMachine.Launch();
            else
                Console.WriteLine("沒初始化");
        }
    }

    static void Main(string[] args)
    {
        TinyIoCContainer tiny = new TinyIoCContainer();
        tiny.Register<IGameMachine, PS3>();
        Player player = tiny.Resolve<Player>();
        player.Play();
        Console.ReadLine();
    }

哈,這里只是注冊了IGameMachine對應PS3,也可以Resolve出Player來,並且通過構造函數創建了PS3呢。

於是,再進一步想一下,假如GameMachine也有依賴的抽象需要實現呢?

那么應用場景再進一步調整:

玩家有一台游戲機,游戲機可以插各種游戲卡帶

那么游戲機就有了一個屬性游戲卡帶,我也希望游戲卡帶能通過構造函數初始化。上面說過的DIP的概念只是說依賴抽象,所以,游戲機從接口抽象改成了抽象類。

 1     class GameBoy : GameMachine
 2     {
 3         protected override void OnPlay()
 4         {
 5             Console.WriteLine("我是任飯,我玩GameBoy!");
 6         }
 7 
 8         public GameBoy(GameCard currentCard) : base(currentCard)
 9         {
10 
11         }
12     }
13 
14     abstract class GameMachine
15     {
16         private GameCard _currentCard;
17 
18         protected GameMachine(GameCard currentCard)
19         {
20             _currentCard = currentCard;
21         }
22 
23         public void Launch()
24         {
25             OnPlay();
26             Console.WriteLine("我在玩{0}", _currentCard.Name);
27         }
28 
29         protected abstract void OnPlay();
30     }
31 
32     public abstract class GameCard
33     {
34         public abstract string Name { get; }
35     }
36 
37     public class PoketMonster:GameCard
38     {
39         public override string Name
40         {
41             get { return "口袋藍"; }
42         }
43     }

稍微更改下Player類,替換接口IGameMachine成抽象類GameMachine。

那么使用的時候,我們在容器中注冊GameCard為PoketMonster,GameMachine為GameBoy試試看。

 1     static void Main(string[] args)
 2     {
 3         TinyIoCContainer tiny = new TinyIoCContainer();
 4         tiny.Register<GameMachine, GameBoy>();
 5         tiny.Register<GameCard, 口袋妖怪>();
 6 
 7         Player p = tiny.Resolve<Player>();
 8         p.Play();
 9 
10         Console.ReadLine();
11     }

運行輸出

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM