Инверсия Контейнеров Контроля и IoC - PullRequest
0 голосов
/ 29 ноября 2018

Я понимаю всю концепцию инверсии управления, но изо всех сил пытаюсь выяснить, где находится контейнер IoC и как он может помочь.

Вот пример.Допустим, у нас есть следующие интерфейсы ...

public interface IWarrior
{
    string Name { get; }
    IWeapon Weapon { get; }
    void EquipWeapon(IWeapon weapon);
    void Attack(ITarget target);
    void DoVictoryDance();
}

public interface IWeapon
{
    int AttackPower { get; }
}

public interface ITarget
{
    int Health { get; }
    int ArmorValue { get; }
    int ReceiveAttack(int damage);
}

Базовый класс IWarrior ...

public abstract class BaseWarrior : IWarrior
{
    private static readonly Random Random = new Random();

    protected BaseWarrior(string name, IWeapon weapon)
    {
        Name = name;
        Weapon = weapon;
    }

    public string Name { get; }
    public IWeapon Weapon { get; private set; }

    public virtual void Attack(ITarget target)
    {
        var attackValue = Random.Next(0, Weapon.AttackPower + 1);

        var damageDone = target.ReceiveAttack(attackValue);

        Console.WriteLine($"{Name} did {damageDone} to {target.GetType().Name}");

        if (target.Health <= 0)
            DoVictoryDance();
    }

    public virtual void EquipWeapon(IWeapon weapon)
    {
        Weapon = weapon;
        Console.WriteLine($"{Name} equips {weapon.GetType().Name}");
    }

    public abstract void DoVictoryDance();
}

Типы бетонных воинов ...

    public class Samurai : BaseWarrior
{
    public Samurai(string name, IWeapon weapon) : base(name, weapon)
    {
    }

    public override void DoVictoryDance()
    {
        Console.WriteLine($"{Name} dances on top of the corpses of his foes.");
    }
}

public class ChuckNorris : BaseWarrior
{
    public ChuckNorris() : base("Chuck Norris", null)
    {
    }

    public override void Attack(ITarget target)
    {
        var targetName = target.GetType().Name;
        Console.WriteLine($"Chuck Norris stares at {targetName}. {targetName} collapses on the floor, dead. {targetName} never saw Chuck Norris.");

        DoVictoryDance();
    }

    public override void EquipWeapon(IWeapon weapon)
    {
        Console.WriteLine("Chuck Norris needs no weapons you fool!");
    }

    public override void DoVictoryDance()
    {
        Console.WriteLine("Chuck Norris doesn't dance. He stares at you until you do it for him.");
    }
}

Следующее оружие ...

public class Sword : IWeapon
{
    public int AttackPower => 10;
}

public class CrossBow : IWeapon
{
    public int AttackPower => 15;
}

И, наконец, основной враг:

public class Bear : ITarget
{
    public int Health { get; private set; } = 100;
    public int ArmorValue => 2;
    public int ReceiveAttack(int damage)
    {
        var damageTaken = damage - ArmorValue;

        if (damageTaken > 0)
            Health -= damageTaken;

        return damageTaken;
    }
}

Мне ясно, что такое инверсия контроля.Мой основной класс не должен знать конкретный тип IWarrior, IWarrior никогда не знает конкретный тип IWeapon или ITarget.

Так что это позволяет мне делать что-то вроде ...

ITarget target = new Bear();
IWarrior warrior = new ChuckNorris();
warrior.Attack(target);

или ...

ITarget target = new Bear()
IWarrior warrior = new Samurai("Ben", new Sword());
warrior.Attack(target);

И я вижу, как было бы проще иметь контейнер, который просто хранит мои объекты, чтобы я не "потерял их след" (я не хочу, чтобы вокруг было много мечей или оружия, например, это могут быть синглтоны).

Примеры, которые я видел для контейнеров IoC, показывают нечто похожее на это:

IocContainer container = new IocContainer();
container.Bind<IWarrior>().To<Samurai>();
container.Bind<IWeapon>().To<Sword>();
container.Bind<ITarget>().To<Bear>();

и затем делает что-то вроде ...

ITarget target = container.Get<ITarget>();
IWarrior warrior = container.Get<IWarrior>();
warrior.Attack(target);

Но теперь я в основном говорю, что мой IWarrior всегда равен Samurai, что мой IWeapon всегда равен Sword, и этомой ITarget всегда Bear.

Это не совсем то, что я хотел!Я хочу иметь возможность создавать различные типы IWarrior с различными комбинациями IWeapon и атаковать множество ITargets!

Возможно, я неправильно понимаю что-то базовое о том, как работает контейнер IoC, но у меня естьЯ видел несколько видео о них (с использованием нескольких библиотек), и все они в основном говорят «1051», когда я хочу «что-то», реализующее интерфейс XX, найдите в своем контейнере объект конкретного типа YY.Если у вас его еще нет, создайте его, сохраните и отправьте мне.

Может кто-нибудь объяснить, в чем преимущества контейнера IoC, приведите реальные примеры его использования?работает и как можно сохранить выбор (не ограничивая IWarrior до Samurai, как указано выше, например)?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...