保举一款Ioc容器之Ninject入门详解

打印 上一主题 下一主题

主题 1767|帖子 1767|积分 5301

随着软件的不断发展,功能越来越复杂,为了将复杂的逻辑简单化,解耦成了架构师,工程师们经常提起的话题,今天我们就以一个简单的小例子,来看一下解耦的好处,顺便介绍一款Ioc容器Ninject的应用,仅供学习分享利用,如有不足之处,还请指正。

假设场景

在武侠小说中,江湖代表着神秘莫测,身不由己,更有传奇色彩浓郁的江湖英雄榜,剑气纵横,枪出如龙,南帝北丐,东邪西毒,不可胜数。今天我们就以刀剑为例进行说明。
比如,有一个剑的类(Sword),它的主要攻击方式为劈,挑等招数,如下所示:
  1. /// <summary>
  2. /// 剑
  3. /// </summary>
  4. public class Sword
  5. {
  6.     public void Hit(string target)
  7.     {
  8.         Console.WriteLine($"剑将 {target} 劈成两半.");
  9.     }
  10. }
复制代码
有一个飞镖的类(Shuriken),它的主要攻击方式为长途飞刺,如下所示:
  1. /// <summary>
  2. /// 手里剑,飞镖
  3. /// </summary>
  4. public class Shuriken
  5. {
  6.     public void Hit(string target)
  7.     {
  8.         Console.WriteLine("手里剑刺破 {0} 的盔甲", target);
  9.     }
  10. }
复制代码
有一位少侠(Samurai),当他用剑时,他的武功招数以劈,挑为主,如下所示:
  1. /// <summary>
  2. /// 武士
  3. /// </summary>
  4. public class Samurai
  5. {
  6.     readonly Sword sword;
  7.     public Samurai()
  8.     {
  9.         this.sword = new Sword();
  10.     }
  11.     /// <summary>
  12.     /// 攻击
  13.     /// </summary>
  14.     /// <param name="target"></param>
  15.     public void Attack(string target)
  16.     {
  17.         this.sword.Hit(target);
  18.     }
  19. }
复制代码
在上述例子中,剑(Sword)做为兵器的一种,在少侠(Samurai)的构造函数中进行创建,并利用,这样少侠(Samurai)和剑(Sword)就形成了强耦合关系(少侠依靠于剑),假如少侠想利用暗器飞镖(Shuriken)作为武器,又该怎样呢?
为相识决这种依靠关系,我们为可以创建接口(interface)来做为剑(Sword)和飞镖(Shuriken)的声明,在这里,我们创建了一个武器接口(IWeapon),它具有攻击的功能(Hit),如下所示:
  1. /// <summary>
  2. /// 武器
  3. /// </summary>
  4. public interface IWeapon
  5. {
  6.     /// <summary>
  7.     /// 攻击
  8.     /// </summary>
  9.     /// <param name="target"></param>
  10.     void Hit(string target);
  11. }
复制代码
而剑(Sword)和飞镖(Shuriken)分别实现武器接口(IWeapon),如下所示:
剑(Sword)的实现类
  1. public class Sword : IWeapon
  2. {
  3.    public void Hit(string target)
  4.    {
  5.        Console.WriteLine("剑将 {0} 劈成两半", target);
  6.    }
  7. }
复制代码
飞镖(Shuriken)的实现类
  1. /// <summary>
  2. /// 手里剑,飞镖
  3. /// </summary>
  4. public class Shuriken : IWeapon
  5. {
  6.    public void Hit(string target)
  7.    {
  8.       Console.WriteLine("手里剑刺破 {0} 的盔甲", target);
  9.    }
  10. }
复制代码
当抽象出来武器接口(IWeapon)后,这样的我们的少侠(Samurai)就可以依靠武器接口(IWeapon),而不是具体的实现剑(Sword)和飞镖(Shuriken),如下所示:
  1. public class Samurai
  2. {
  3.     readonly IWeapon weapon;
  4.     public Samurai(IWeapon weapon)
  5.     {
  6.         this.weapon = weapon;
  7.     }
  8.     public void Attack(string target)
  9.     {
  10.         this.weapon.Hit(target);
  11.     }
  12. }
复制代码
当少侠(Samurai)想用剑(Sword)时,就传入剑的实现,想用飞镖(Shuriken)时,就传入飞镖的实现,如下所示:
  1. class Program
  2. {
  3.     public static void Main()
  4.     {
  5.         var warrior1 = new Samurai(new Shuriken());//飞镖少侠
  6.         var warrior2 = new Samurai(new Sword());//用剑少侠
  7.         warrior1.Attack("坏人");
  8.         warrior2.Attack("坏人");
  9.     }
  10. }
复制代码
以上就是面向接口编程的根本实现,只是接纳手动的方式进行解耦(需要手动的创建对象),接下来我们将依靠Ioc容器进行主动创建解耦。
Ninject

首先安装Ninject库,在Visual Studio 2022中,可以通过Nuget包管理器进行安装,如下所示:

创建TestModule类,它继承自NinjectModule类,重写Load方法并在Load方法中,通过Bind绑定接口的实现,如下所示:
  1. public class TestModule : NinjectModule
  2. {
  3.     public override void Load()
  4.     {
  5.         Bind<IWeapon>().To<Sword>();
  6.         Bind<Samurai>().ToSelf().InSingletonScope();
  7.     }
  8. }
复制代码
Ninject提供了一个IKernel接口,以及对接口的尺度实现(StandardKernel),在创建IKernel对象时,传递TestModule实例对象,这样就可以获取少侠(Samurai)实例对象,且主动识别依靠关系,并创建注入的IWeapon接口对象,如下所示:
  1. class Program
  2. {
  3.     public static void Main()
  4.     {
  5.         IKernel kernel = new StandardKernel(new TestModule());
  6.         Samurai warrior = kernel.Get<Samurai>();
  7.         warrior.Attack("坏人");
  8.     }
  9. }
复制代码
在上述示例中,注入的兵器接口(IWeapon)的实现接口为剑(Sword),则少侠(Samurai)主动匹配剑的攻击方式,如下所示:

那么如果少侠(Samurai)在利用剑(Sword)的时候,又想利用飞镖(Shuriken),就是少侠(Samurai)想同时利用两种或多种兵器(IWeapon),这样才能让敌人防不胜防,我们该怎样做呢?
接下来,我们修改少侠类(Samurai),将依靠的IWeapon接口改为接口数组,在构造函数中传入IWeapon接口数组,如下所示:
  1. public class Samurai
  2. {
  3.     readonly IWeapon[] weapons;
  4.     public Samurai(IWeapon[] weapons)
  5.     {
  6.         this.weapons = weapons;
  7.     }
  8.     public void Attack(string target)
  9.     {
  10.         foreach (var weapon in weapons)
  11.         {
  12.             weapon.Hit(target);
  13.         }
  14.     }
  15. }
复制代码
然后在TestModule类中注入兵器(IWeapon)的两个实现剑(Sword)和飞镖(Shuriken),如下所示:
  1. public class TestModule : NinjectModule
  2. {
  3.     public override void Load()
  4.     {
  5.         Bind<IWeapon>().To<Sword>();
  6.         Bind<IWeapon>().To<Shuriken>();
  7.         Bind<Samurai>().ToSelf().InSingletonScope();
  8.     }
  9. }
复制代码
通过Ioc容器获取少侠(Samurai)实例的方式不变,运行程序,发现少侠(Samurai)在与对手比武时,同时利用了两种功法(Attack),如下所示:

参考文档

关于Ninject的应用还有很多,本文只是简略介绍,更多内容,可参考官方文档:https://github.com/ninject/Ninject/wiki
 
以上就是《保举一款Ioc容器之Ninject入门详解》的全部内容,旨在抛砖引玉,一起学习,共同进步

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
继续阅读请点击广告

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

瑞星

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表