zoukankan      html  css  js  c++  java
  • 初试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     }

    运行输出

     

  • 相关阅读:
    Microsoft.Office.Interop.Excel 组件的报错检索 COM 类工厂中 CLSID,错误码:80070005
    SQLServer编写自己的切分函数 SPLIT和带排序的切割函数 SPLITSort
    Powerdesigner 导出Excel格式数据字典 导出Excel格式文件
    NPOI 导入导出excel两种方式 和 错误 无法访问已关闭的流解决方式
    unable to start the virtual device;Genymotion启动安卓模拟器出错
    datetimepicker 时间控件 1899年问题以及解决方法
    Linux命令大全
    Linux工具包
    Redis
    MySQL索引
  • 原文地址:https://www.cnblogs.com/pasoraku/p/4502967.html
Copyright © 2011-2022 走看看