Ninject: standard and specific bindings for the Generic class

I have an abstract class:

public abstract class Validator<T> : IValidator 

and several classes that implement this class for specific purposes, for example

 public sealed class NewsValidator : Validator<News> 

Now, using Ninject, I want to make Injection Dependency as follows (this specific code DOES NOT work):

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

So I want to achieve that

 Validator<News> 

Must be bound to the NewsValidator class, but if any other unrelated version of this class is requested, say

 Validator<Article> Validator<SomethingElse> 

which should be bound to the default class (NullValidator). The use of the code used above raises an exception, though, since it binds the Validator <News> to both NewsValidator and NullValidator.

How could I implement this? Separate types of a generic class must be bound to separate classes. All other types of the general class that were not explicitly bound must be bound to the default class.

Would be really happy with some suggestions! Thanks!

+6
source share
1 answer

You can create a custom implementation of IMissingBindingResolver .

Whenever the kernel fails to resolve the binding for the requested service, it delegates the HandleMissingBinding method (this is true for any kernel obtained from KernelBase ). The HandleMissingBinding method will request every missing binding resolver if it can create a binding for the requested service. Links returned by resolvers, if any, will be added to the kernel.

Note that any binding created by a missing binding resolver will be added to the kernel as an implicit binding. This may affect your application. For example, if you have a mixture of explicit and implicit bindings for a service, resolving these bindings, i.e. kernel.GetAll<TService>() , only allows explicit bindings. However, if all bindings are implicit, they will all be allowed.

Ninject has two standard implementations of IMISingBindingResolver:

Let me implement a custom converter for empty validators.

 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 }; } } 

Now the next test passes (using 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); } 
+9
source

Source: https://habr.com/ru/post/889655/


All Articles