Ninject: стандартные и специальные привязки для универсального класса

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

 public abstract class Validator<T> : IValidator

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

public sealed class NewsValidator : Validator<News>

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

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

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

Validator<News>

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

Validator<Article>
Validator<SomethingElse>

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

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

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


person Oliver    schedule 02.06.2011    source источник


Ответы (1)


Вы можете создать собственную реализацию 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);
}
person mrydengren    schedule 02.06.2011
comment
вау :) Невероятно, это работает как шарм. Как ты это узнал?! Даже Google не находит многого при поиске IMissingBindingResolver. В любом случае, это абсолютно идеально, большое спасибо!! - person Oliver; 03.06.2011