推荐一款Ioc容器之Ninject入门详解-牛翰网

推荐一款Ioc容器之Ninject入门详解

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

假设场景

在武侠小说中,江湖代表着神秘莫测,身不由己,更有传奇色彩浓郁的江湖英雄榜,剑气纵横,枪出如龙,南帝北丐,东邪西毒,数不胜数。今天我们就以刀剑为例进行说明。

比如,有一个剑的类(Sword),它的主要攻击方式为劈,挑等招数,如下所示:

/// <summary>
/// 剑
/// </summary>
public class Sword
{
    public void Hit(string target)
    {
        Console.WriteLine($"剑将 {target} 劈成两半.");
    }
}

有一个飞镖的类(Shuriken),它的主要攻击方式为远程飞刺,如下所示:

/// <summary>
/// 手里剑,飞镖
/// </summary>
public class Shuriken
{
    public void Hit(string target)
    {
        Console.WriteLine("手里剑刺破 {0} 的盔甲", target);
    }
}

有一位少侠(Samurai),当他用剑时,他的武功招数以劈,挑为主,如下所示:

/// <summary>
/// 武士
/// </summary>
public class Samurai
{
    readonly Sword sword;
    public Samurai()
    {
        this.sword = new Sword();
    }

    /// <summary>
    /// 攻击
    /// </summary>
    /// <param name="target"></param>
    public void Attack(string target)
    {
        this.sword.Hit(target);
    }
}

在上述例子中,剑(Sword)做为兵器的一种,在少侠(Samurai)的构造函数中进行创建,并使用,这样少侠(Samurai)和剑(Sword)就形成了强耦合关系(少侠依赖于剑),假如少侠想使用暗器飞镖(Shuriken)作为武器,又该如何呢?

为了解决这种依赖关系,我们为可以创建接口(interface)来做为剑(Sword)和飞镖(Shuriken)的声明,在这里,我们创建了一个武器接口(IWeapon),它具有攻击的功能(Hit),如下所示:

/// <summary>
/// 武器
/// </summary>
public interface IWeapon
{
    /// <summary>
    /// 攻击
    /// </summary>
    /// <param name="target"></param>
    void Hit(string target);
}

而剑(Sword)和飞镖(Shuriken)分别实现武器接口(IWeapon),如下所示:

剑(Sword)的实现类

public class Sword : IWeapon
{
   public void Hit(string target)
   {
       Console.WriteLine("剑将 {0} 劈成两半", target);
   }
}

飞镖(Shuriken)的实现类

/// <summary>
/// 手里剑,飞镖
/// </summary>
public class Shuriken : IWeapon
{
   public void Hit(string target)
   {
      Console.WriteLine("手里剑刺破 {0} 的盔甲", target);
   }
}

当抽象出来武器接口(IWeapon)后,这样的我们的少侠(Samurai)就可以依赖武器接口(IWeapon),而不是具体的实现剑(Sword)和飞镖(Shuriken),如下所示:

public class Samurai
{
    readonly IWeapon weapon;
    public Samurai(IWeapon weapon)
    {
        this.weapon = weapon;
    }

    public void Attack(string target)
    {
        this.weapon.Hit(target);
    }
}

当少侠(Samurai)想用剑(Sword)时,就传入剑的实现,想用飞镖(Shuriken)时,就传入飞镖的实现,如下所示:

class Program
{
    public static void Main()
    {
        var warrior1 = new Samurai(new Shuriken());//飞镖少侠
        var warrior2 = new Samurai(new Sword());//用剑少侠
        warrior1.Attack("坏人");
        warrior2.Attack("坏人");
    }
}

以上就是面向接口编程的基本实现,只是采用手动的方式进行解耦(需要手动的创建对象),接下来我们将依赖Ioc容器进行自动创建解耦。

Ninject

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

创建TestModule类,它继承自NinjectModule类,重写Load方法并在Load方法中,通过Bind绑定接口的实现,如下所示:

public class TestModule : NinjectModule
{
    public override void Load()
    {
        Bind<IWeapon>().To<Sword>();
        Bind<Samurai>().ToSelf().InSingletonScope();
    }
}

Ninject提供了一个IKernel接口,以及对接口的标准实现(StandardKernel),在创建IKernel对象时,传递TestModule实例对象,这样就可以获取少侠(Samurai)实例对象,且自动识别依赖关系,并创建注入的IWeapon接口对象,如下所示:

class Program
{
    public static void Main()
    {
        IKernel kernel = new StandardKernel(new TestModule());
        Samurai warrior = kernel.Get<Samurai>();
        warrior.Attack("坏人");
    }
}

在上述示例中,注入的兵器接口(IWeapon)的实现接口为剑(Sword),则少侠(Samurai)自动匹配剑的攻击方式,如下所示:

那么如果少侠(Samurai)在使用剑(Sword)的时候,又想使用飞镖(Shuriken),就是少侠(Samurai)想同时使用两种或多种兵器(IWeapon),这样才能让敌人防不胜防,我们该如何做呢?

接下来,我们修改少侠类(Samurai),将依赖的IWeapon接口改为接口数组,在构造函数中传入IWeapon接口数组,如下所示:

public class Samurai
{
    readonly IWeapon[] weapons;
    public Samurai(IWeapon[] weapons)
    {
        this.weapons = weapons;
    }

    public void Attack(string target)
    {
        foreach (var weapon in weapons)
        {
            weapon.Hit(target);
        }
    }
}

然后在TestModule类中注入兵器(IWeapon)的两个实现剑(Sword)和飞镖(Shuriken),如下所示:

public class TestModule : NinjectModule
{
    public override void Load()
    {
        Bind<IWeapon>().To<Sword>();
        Bind<IWeapon>().To<Shuriken>();
        Bind<Samurai>().ToSelf().InSingletonScope();
    }
}

通过Ioc容器获取少侠(Samurai)实例的方式不变,运行程序,发现少侠(Samurai)在与对手比武时,同时使用了两种功法(Attack),如下所示:

参考文档

关于Ninject的应用还有很多,本文只是简略介绍,更多内容,可参考官方文档:https://github.com/ninject/Ninject/wiki

 

以上就是《推荐一款Ioc容器之Ninject入门详解》的全部内容,旨在抛砖引玉,一起学习,共同进步

来源链接:https://www.cnblogs.com/hsiang/p/18805244

请登录后发表评论

    没有回复内容