문제

I'm getting a 'not registered error' during execution in the ValidatorFactory.CreateInstance call. It appears the type being sent into the method is correct.

My registration code:

...
builder.RegisterAssemblyTypes(assembly).Where(t => t.Name.EndsWith("Validator")).As<IValidator>();
builder.Register(d => _containerProvider).As<IContainerProvider>();
builder.Register(d => new ValidatorFactory(_containerProvider.ApplicationContainer.Resolve<IContainerProvider>())).As<IValidatorFactory>();

_containerProvider = new ContainerProvider(builder.Build());

My ValidatorFactory code:

public class ValidatorFactory : ValidatorFactoryBase {
    private readonly IContainerProvider _containerProvider;

    public ValidatorFactory(IContainerProvider containerProvider) {
        _containerProvider = containerProvider;
    }

    public override IValidator CreateInstance(Type validatorType) {
        return _containerProvider.ApplicationContainer.Resolve<IValidator>(validatorType);
    }
}

My view model and validator code:

[Validator(typeof(EmployeeViewModelValidator))]
public class EmployeeViewModel {
    public EmployeeViewModel() {}
    public EmployeeViewModel(string firstName) {
        FirstName = firstName;
    }

    public string FirstName { get; private set; }
}

public class EmployeeViewModelValidator : AbstractValidator<EmployeeViewModel> {
    public EmployeeViewModelValidator() {
        RuleFor(x => x.FirstName)
            .NotEmpty();
    }
}

My best guess is that I'm registering the validators wrong.

도움이 되었습니까?

해결책 3

Current Registration Code:

builder.RegisterType<EmployeeViewModelValidator>().Keyed<IValidator>(typeof(EmployeeViewModel));
builder.RegisterType<ValidatorFactory>().As<IValidatorFactory>();

_containerProvider = new ContainerProvider(builder.Build());

Current ValidatorFactory:

public class ValidatorFactory : ValidatorFactoryBase {
    readonly IIndex<Type, IValidator> _validators; 

    public ValidatorFactory(IIndex<Type, IValidator> validators) {
        _validators = validators;
    } 

    public override IValidator CreateInstance(Type validatorType) {
        return _validators[validatorType];
    }
}

Same error inside CreateInstance:

The requested service 'FluentValidation.IValidator`1[.EmployeeViewModel] (FluentValidation.IValidator)' has not been registered.

다른 팁

To resolve from multiple classes that implement IValidator, the autofac documentation shows a couple of techniques. I don't think you can use assembly scanning with these methods; you'll have register the validators individually.

By Name

builder.RegisterType<EmployeeViewModelValidator>().Named<IValidator>("employee");

var r = container.Resolve<IValidator>("employee");

By Key

The documentation shows an enumeration being used as a key, but you could use the type as the key, which would let you call Resolve using the validatorType being passed to you in the CreateInstance method.

builder.RegisterType<EmployeeViewModelValidator>().Keyed<IValidator>(typeof(EmployeeViewModelValidator));    

var r = container.Resolve<IValidator>(validatorType);

Note: The documentation is for version 2.3 of Autofac. I'm using 2.2.4, which is why the method names above vary from the documentation.

Hope this helps.

The other answer by @adrift is a nice clean approach. Just to add some notes, this also works with the IIndex<K,V> relationship type, which Autofac provides automatically, e.g.:

public class ValidatorFactory : ValidatorFactoryBase {
    readonly IIndex<Type, IValidator> _validators;

    public ValidatorFactory(IIndex<Type, IValidator> validators) {
        _validators = validators;
    }

    public override IValidator CreateInstance(Type validatorType) {
        return _validators[validatorType];
    }
}

Important note: don't use IContainerProvider and ApplicationContainer in a component—instead use IComponentContext or IIndex<K,V> as above. This will help prevent lifetime issues (your example associates validators with the application rather than the request lifetime.)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top