初试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     }

运行输出

 初试TinyIoCContainer笔记

你可能感兴趣的:(contain)