依赖注入连线问题

时间:2009-12-17 22:43:29

标签: c# dependency-injection inversion-of-control unity-container ninject

如果有3个界面,如下所示

public interface IWeapon {
void Kill();
}

public interface ISword:IWeapon {
void Slice();
}

public interface IShuriken: IWeapon {
void Pierce();
}

public class Ninja {
public IWeapon Weapon {get;set;}
public void BrutalKill() {

/* warrior must pierce, pierce, pierce and then kill 


*/

}
public void HonorKill {
/* warrior must kill by one slice */
}
}

对于这样的场景,你会如何对容器进行连接以及你的方法体对于BrutalKill和HonorKill会是什么样的?

编辑:根据评论,我正在思考一个忍者应该携带武器......如果它想要武装剑或手里剑...应该稍后决定......不确定是否我正在思考..也许我们需要将Ninja子类化为NinjaWithShuriken和NinjaWithSword

4 个答案:

答案 0 :(得分:3)

不确定这是否是您要找的,但我会这样:

// first some implementations
public class Sword : ISword {
    public void Kill() { // imp }
    public void Slice() { // imp }
}

public class Shuriken : IShuriken {
    public void Kill() { // imp }
    public void Pierce() { // imp }
}

// and I would change the Ninja class to
public class Ninja {
    public ISword Sword { get; private set; }
    public IShuriken Shuriken { get; private set; }

    public Ninja(ISword sword, IShuriken shuriken) {
        this.Sword = sword;
        this.Shuriken = shuriken;
    }

    public void BrutalKill() {
        Shuriken.Pierce();
        Shuriken.Pierce();
        Shuriken.Pierce();

        // either weapon can kill
        // so lets close the distance and use the sword
        Sword.Kill();
    }

    public void HonorKill {
        Sword.Slice();
    }
}

// creating the class
// where Ioc.Resolve is specific to the container implementation
var ninja = new Ninja(IoC.Resolve<ISword>(), IoC.Resolve<IShuriken>());

<强>更新 我喜欢Phil Sandler的评论,所以快速更新以反映:

// a ninja interface
public interface INinja {
    void BrutalKill();
    void HonorKill();
}

// and then update the ninja class to
public Ninja : INinja {
    ...
}

// and have the ninja class created like this with the container
// resolving the dependencies:
var ninja = IoC.Resolve<INinja>();

<强>更新 根据对原始问题的更新,我会说:

public interface IWeapon {
    void Attack();
    void Kill();
}

public class Sword : ISword {
    public void Attack() {
        // implement as a slash
    }
    ...
}

public class Shuriken : IShuriken {
    public void Attack() {
        // implement as a pierce
    }
    ...
}

我们并不真正关心Sword和Shuriken如何实施攻击,只要忍者能够在被召唤时使用它们来履行其职责。只要工作在所述协议的范围内完成,在这种情况下通过攻击,就可以暗杀暗杀具体的指令。

// create the specific ninja
var swordNinja = new Ninja(IoC.Resolve<ISword>());
var shurikenNinja = new Ninja(IoC.Resolve<IShuriken>());

// with the ninja class updated to only have an IWeapon 
// property that gets set in the constructor.

答案 1 :(得分:1)

如果你的忍者能够获得BrutalKill和HonorableKill,他绝对必须拥有一个ISword和一个IShuriken。忍者依赖于这些,所以我们在ctor中声明它们:

public class Ninja
{
    readonly IShuriken shuriken;
    readonly ISword sword;

    public Ninja(IShuriken sh, ISword sw)
    {
        shuriken = sh;
        sword = sw;
    }

    public void BrutalKill()
    {
        shuriken.Pierce();
        shuriken.Pierce();
        shuriken.Pierce();
        sword.Slice();
        shuriken.Kill();
    }

    public void HonorKill()
    {
        sword.Slice();
        sword.Kill();
    }
}

这是我们的武器:

public interface IWeapon
{
    void Kill();
}

public interface IShuriken : IWeapon
{
    void Pierce();
}

public interface ISword : IWeapon
{
    void Slice();
}

让我们来看看这些依赖项的几个实现:

using System;

public class BronzeShuriken : IShuriken
{
    public void Pierce()
    {
        Console.WriteLine("Bronze shuriken pierce time now!");
    }

    public void Kill()
    {
        Console.WriteLine("Bronze shuriken kill!!!");
    }
}

public class RustySword : ISword
{
    public void Slice()
    {
        Console.WriteLine("Rusty sword slice time now!");
    }

    public void Kill()
    {
        Console.WriteLine("Rusty sword kill!!!");
    }
}

我们的配置如下:

using Ninject.Modules;

class DefaultModule : NinjectModule
{
    public override void Load()
    {
        Bind<IShuriken>().To<BronzeShuriken>();
        Bind<ISword>().To<RustySword>();
    }
}

我们的切入点如下:

    static void Main()
    {
        using (var kernel = new StandardKernel())
        {
            kernel.Load(new DefaultModule());

            kernel.Get<Ninja>().BrutalKill();
        }
    }

答案 2 :(得分:1)

Kill(),没有参数,似乎是在命令忍者自杀。我会定义Ninja来对其他忍者采取行动:

public interface INinja
{
    void KillBrutally(INinja otherNinja);

    void KillHonorably(INinja otherNinja);
}

然后,提高武器的抽象等级来杀死移动:

public interface IKillMove
{
    void Kill(INinja ninja);
}

让ninjas支持杀戮类型:

public sealed class Ninja : INinja
{
    private readonly IKillMove _brutalKillMove;
    private readonly IKillMove _honorableKillMove;

    public Ninja(IKillMove brutalKillMove, IKillMove honorableKillMove)
    {
        _brutalKillMove = brutalKillMove;
        _honorableKillMove = honorableKillMove;
    }

    #region INinja

    public void KillBrutally(INinja otherNinja)
    {
        _brutalKillMove.Kill(otherNinja);
    }

    public void KillHonorably(INinja otherNinja)
    {
        _honorableKillMove.Kill(otherNinja);
    }
    #endregion
}

现在我们可以担心武器了:

public interface IWeapon
{
    void Attack(INinja ninja);

    void Finish(INinja ninja);
}

并杀死动作:

public sealed class MoveInKillMove : IKillMove
{
    private readonly IWeapon _shortRangeWeapon;
    private readonly IWeapon _longRangeWeapon;

    public MoveInKillMove(IWeapon shortRangeWeapon, IWeapon longRangeWeapon)
    {
        _shortRangeWeapon = shortRangeWeapon;
        _longRangeWeapon = longRangeWeapon;
    }

    #region IKillMove

    public void Kill(INinja ninja)
    {
        _longRangeWeapon.Attack(ninja);
        _longRangeWeapon.Attack(ninja);
        _longRangeWeapon.Attack(ninja);

        _shortRangeWeapon.Finish(ninja);
    }
    #endregion
}

public sealed class FinishingMove : IKillMove
{
    private readonly IWeapon _weapon;

    public FinishingMove(IWeapon weapon)
    {
        _weapon = weapon;
    }

    #region IKillMove

    public void Kill(INinja ninja)
    {
        _weapon.Finish(ninja);
    }
    #endregion
}

以下是一个示例布线(根据需要转换为您的IoC容器):

var sword = new Sword();

var ninja = new Ninja(
    new MoveInKillMove(sword, new Shuriken()),
    new FinishingMove(sword));

答案 3 :(得分:0)

团结一致:

Container.RegisterType<INinja,Ninja>();
Container.RegisterType<ISword,Sword>();
Container.RegisterType<IShuriken,Shuriken>();

假设Ninja同时拥有Sword和Shuriken,因为只有Sword可以切片且只有Shuriken可以刺穿。

此外,Ninja有一个接受IShuriken和ISword作为参数的构造函数。

所以要忍者,

var ninja= Container.Resolve<INinja>();