Asp.net Core AutoFac registers using factory

I am using Asp.net Core with AutoFac and follow the answers accepted here:

Validation: how to enter model state wrapper using Ninject?

In this case, ninject is used. I do not understand how to make the equivalent of this ninject part in autoFac, in particular kernel.Get :

 Func<Type, IValidator> validatorFactory = type => { var valType = typeof(Validator<>).MakeGenericType(type); return (IValidator)kernel.Get(valType); }; kernel.Bind<IValidationProvider>() .ToConstant(new ValidationProvider(validatorFactory)); 

Startup.cs

 public IServiceProvider ConfigureServices(IServiceCollection services) { var containerBuilder = new ContainerBuilder(); IValidator ValidatorFactory(Type type) { var valType = typeof(Validator<>).MakeGenericType(type); //This line is the problem // return (IValidator)container.Resolve(valType); } containerBuilder.Register(x => new ValidationProvider(ValidatorFactory)).As<IValidationProvider>().SingleInstance(); containerBuilder.RegisterType<UploadValidator>().As<Validator<AudioModel>>(); containerBuilder.Populate(services); var container = containerBuilder.Build(); return container.Resolve<IServiceProvider>(); } 

The problem is that the container is only available after using .Build() , so I don’t see how to do it. Is it necessary to register this service after calling .Build() and then calling .Build() again, or is this .Resolve() wrong use here.

Validation Classes:

 internal sealed class ValidationProvider : IValidationProvider { private readonly Func<Type, IValidator> _validatorFactory; public ValidationProvider(Func<Type, IValidator> validatorFactory) { _validatorFactory = validatorFactory; } public void Validate(object entity) { var results = _validatorFactory(entity.GetType()).Validate(entity).ToArray(); if (results.Length > 0) throw new ValidationException(results); } public void ValidateAll(IEnumerable entities) { var results = ( from entity in entities.Cast<object>() let validator = _validatorFactory(entity.GetType()) from result in validator.Validate(entity) select result).ToArray(); if (results.Length > 0) throw new ValidationException(results); } } public abstract class Validator<T> : IValidator { IEnumerable<ValidationResult> IValidator.Validate(object entity) { if (entity == null) throw new ArgumentNullException(nameof(entity)); return Validate((T)entity); } protected abstract IEnumerable<ValidationResult> Validate(T entity); } public class UploadValidator : Validator<AudioModel> { protected override IEnumerable<ValidationResult> Validate(AudioModel model) { if (string.IsNullOrWhiteSpace(model.Name)) { yield return new ValidationResult("Name", "Name is required"); } } } 
+1
c # ninject autofac
Jul 18 '17 at 16:06
source share
1 answer

Autofac has an excellent ability to register factories to create instances based on parameters (s). In your example, we could register Func<Type, IValidator> with Autofac and automatically insert it into our ValidationProvider .

 var builder = new ContainerBuilder(); builder //register our factory function .Register<Func<Type, IValidator>>( x => { //get a reference to the scoped container //eg if this is a web app, each HTTP request will //spawn a child container used for the lifetime of that request var context = x.Resolve<IComponentContext>(); return type => { //create the validator from our scoped container var valType = typeof(Validator<>).MakeGenericType(type); return (IValidator) context.Resolve(valType); } } )}; public class ValidationProvider { readonly Func<Type, IValidator> _factory; //Autofac will see this class requires our previously registered //function and inject this for us public ValidationProvider(Func<Type, IValidator> factory) { _factory = factory; } } 

Alternatively, can IValidator be limited IValidator common argument? It may not be practical to reorganize the code, but if so, it might be better to use our services for the exact dependencies that they need, rather than a factory that can hide their intentions.

 public interface IValidator<T> { void Validate(T instance); } public class SomeClassRequiringAudioModelValidator { readonly IValidator<AudioModel> _validator; public SomeClassRequiringAudioModelValidator(IValidator<AudioModel> validator) { _validator = validator; } } 
+1
Jul 19 '17 at 8:52
source share



All Articles