I have an abstract class:
public abstract class Validator<T> : IValidator
and a couple of classes that implement this class for specific purposes, e.g.
public sealed class NewsValidator : Validator<News>
Now using Ninject i want to do Dependency Injection like the following (this particular code is NOT working):
Bind<Validator<News>>().To<NewsValidator>();
Bind(typeof(Validator<>)).To(typeof(NullValidator<>));
So what I want to achieve is that
Validator<News>
Should be bound to the Class "NewsValidator", but if any other not-bound version of this class is requested, say
Validator<Article>
Validator<SomethingElse>
that should be bound to a default Class (NullValidator). Using the code used above throws an Exception, though, because it binds the Validator < News > both to the NewsValidator as well as to the NullValidator.
How could I implement this? Particular types of the generic class should be bound to individual classes. All other types of the generic class that were not explicitly bound should be bound to a default class.
Would be really glad about a couple of suggestions! Thanks!
Ninject is a lightweight dependency injection framework for . NET applications. It helps you split your application into a collection of loosely-coupled, highly-cohesive pieces, and then glue them back together in a flexible manner.
Step 1: We are creating an instance of Class StandardKernel. Step 2: Then we will load the Kernel. Step 3: Get the instance of the specific service that we want to inject. Step 4: Then inject the dependency.
The Ninject modules are the tools used to register the various types with the IoC container. The advantage is that these modules are then kept in their own classes. This allows you to put different tiers/services in their own modules.
You could create a custom implementation of IMissingBindingResolver.
Whenever the kernel fails to resolve a binding for a requested service it delegates to the HandleMissingBinding method (this is true for any kernel derived from KernelBase). The HandleMissingBinding method will ask every missing binding resolver if it can create a binding for the requested service. The bindings returned by the 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 could have implication on 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 resolves explicit bindings. However, if all bindings are implicit they will all be resolved.
Ninject has two standard implementations of IMissingBindingResolver:
Let's implement a custom resolver for the null 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 following test (using xUnit.net) passes.
[Fact]
public void ShouldResolveNonBoundValidatorDerivedFromValidatorAsNullValidator()
{
var kernel = new StandardKernel();
kernel.Components.Add<IMissingBindingResolver, MissingValidatorResolver>();
var validator = kernel.Get<Validator<Article>>();
Assert.IsType<NullValidator<Article>>(validator);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With