
·您现在的位置: 云翼网络 >> 文章中心 >> 网站建设 >> 网站建设开发 >> ASP.NET网站开发 >> 初试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 }
运行输出
