Как избежать необходимости ссылки на Ninject в целевой сборке внедрения при использовании контекстной привязки - PullRequest
1 голос
/ 11 июня 2019

Я смотрю на контекстную привязку с Ninject .Это для случаев, когда у вас есть несколько реализаций некоторой абстракции, и контекст в целевом классе внедрения определяет, какая из этих реализаций внедрена.

В документации пример с использованием «именованных привязок» выглядит следующим образом:

Bind<IWeapon>().To<Shuriken>().Named("Strong");
Bind<IWeapon>().To<Dagger>().Named("Weak");

class WeakAttack {
    readonly IWeapon _weapon;
    public WeakAttack([Named("Weak")] IWeapon weakWeapon){
        _weapon = weakWeapon;
    }
    public void Attack(string victim){
        Console.WriteLine(_weapon.Hit(victim));
    }
}

Это означает, что сборка, содержащая WeakAttack, очевидно, должна будет ссылаться на Ninject, чтобы использовать NamedAttribute в конструкторе.Цель внедрения зависимости не должна знать, какой контейнер DI используется.Что мне здесь не хватает?

1 Ответ

2 голосов
/ 11 июня 2019

Один из способов сделать это - с помощью пользовательских атрибутов, определенных в целевой сборке:

public class BirdAttribute : Attribute { }
public class MonkeyAttribute : Attribute { }
public interface IAnimal { }
public class Bird : IAnimal { }
public class Monkey : IAnimal { }

Использовать пользовательские атрибуты в аргументах конструктора, например:

public class BirdCage
{
    public BirdCage([Bird]IAnimal bird) => Bird = bird;
    public IAnimal Bird { get; }
}

public class Zoo
{
    public Zoo([Monkey]IAnimal monkey, [Bird]IAnimal bird)
    {
        Monkey = monkey;
        Bird = bird;
    }

    public IAnimal Monkey { get; }
    public IAnimal Bird { get; }
}

И привязкибудет использовать WhenTargetHas, например, так:

internal class Module : NinjectModule
{
    public override void Load()
    {
        Bind<IAnimal>().To<Bird>().WhenTargetHas<BirdAttribute>();
        Bind<IAnimal>().To<Monkey>().WhenTargetHas<MonkeyAttribute>();
    }
}

Это поддерживает правильное направление инверсии управления, потому что сборка с привязками Ninject знает о цели (т.е. пользовательских атрибутах), но цель не 'нужно знать, какой контейнер IoC используется.

...