Ninject: стандартные и специальные привязки для общего класса - PullRequest
6 голосов
/ 02 июня 2011

У меня есть абстрактный класс:

 public abstract class Validator<T> : IValidator

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

public sealed class NewsValidator : Validator<News>

Теперь, используя Ninject, я хочу сделать Dependency Injection, как показано ниже (этот конкретный код НЕ работает):

Bind<Validator<News>>().To<NewsValidator>();
Bind(typeof(Validator<>)).To(typeof(NullValidator<>));

Итак, чего я хочу добиться, так это

Validator<News>

Должен быть привязан к классу "NewsValidator", но если запрашивается любая другая не связанная версия этого класса, скажем

Validator<Article>
Validator<SomethingElse>

, который должен быть связан с классом по умолчанию (NullValidator). Использование вышеприведенного кода вызывает исключение, поскольку оно связывает Validator как с NewsValidator, так и с NullValidator.

Как я мог это реализовать? Отдельные типы универсального класса должны быть привязаны к отдельным классам. Все другие типы универсального класса, которые не были явно связаны, должны быть связаны с классом по умолчанию.

Был бы очень рад пару предложений! Спасибо!

1 Ответ

9 голосов
/ 03 июня 2011

Вы можете создать собственную реализацию IMissingBindingResolver .

Когда ядру не удается разрешить привязку для запрошенной службы, оно делегирует методу HandleMissingBinding (этоверно для любого ядра, полученного из KernelBase ).Метод HandleMissingBinding запросит у каждого отсутствующего распознавателя привязок, может ли он создать привязку для запрошенной службы.Привязки, возвращаемые распознавателями, если таковые имеются, будут добавлены в ядро.

Обратите внимание, что любая привязка, созданная отсутствующим преобразователем привязок, будет добавлена ​​в ядро ​​как неявная привязка.Это может иметь последствия для вашего приложения.Например, если у вас есть смесь явных и неявных привязок для службы, разрешение этих привязок, то есть kernel.GetAll<TService>(), разрешает только явные привязки.Однако, если все привязки неявны, все они будут разрешены.

Ninject имеет две стандартные реализации IMissingBindingResolver:

Давайте реализуем собственный распознаватель для пустых валидаторов.

public class MissingValidatorResolver : NinjectComponent, IMissingBindingResolver
{
    public IEnumerable<IBinding> Resolve(
        Multimap<Type, IBinding> bindings, IRequest request)
    {
        var service = request.Service;
        if (!typeof(IValidator).IsAssignableFrom(service))
        {
            return Enumerable.Empty<IBinding>();
        }

        var type = service.GetGenericArguments()[0];
        var validatorType = typeof(NullValidator<>).MakeGenericType(type);

        var binding = new Binding(service)
        {
            ProviderCallback = StandardProvider.GetCreationCallback(validatorType)
        };

        return new[] { binding };
    }
}

Теперь следующий тест (с использованием xUnit.net )проходит.

[Fact]
public void ShouldResolveNonBoundValidatorDerivedFromValidatorAsNullValidator()
{
    var kernel = new StandardKernel();
    kernel.Components.Add<IMissingBindingResolver, MissingValidatorResolver>();

    var validator = kernel.Get<Validator<Article>>();
    Assert.IsType<NullValidator<Article>>(validator);
}
...