AbstractValidator类总是单例,尽管被注册为瞬态

时间:2017-08-19 09:19:06

标签: c# asp.net simple-injector fluentvalidation

我正在使用SimpleInjector 4和FluentValidation 7.我的AbstractValidator依赖于我的DbContext

public class Validator : AbstractValidator<LocationModel>
{
    public LocationModelValidator(IReadOnlyRepository repository)
    {
        // Check the database to see if this location is already present
        RuleFor(x => x.LocationId).Must(x => !repository.Location.Any(i => i.LocationId == x)).WithMessage("A Location with this ID already exists.");
    }
}

我的作品根看起来如下:

var container = new Container();
container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();

container.Register<IReadOnlyRepository, LocationDbContext>(Lifestyle.Scoped);
container.Register<IValidatorFactory>(() => new ServiceProviderValidatorFactory(GlobalConfiguration.Configuration));
container.Register(typeof(IValidator<>), assemblies, Lifestyle.Scoped);

container.RegisterWebApiControllers(GlobalConfiguration.Configuration);

container.Verify();

GlobalConfiguration.Configuration.DependencyResolver = 
    new SimpleInjectorWebApiDependencyResolver(container);

ValidatorFactory实现

public class ServiceProviderValidatorFactory : ValidatorFactoryBase
{
    private readonly HttpConfiguration _config;

    public ServiceProviderValidatorFactory(HttpConfiguration config)
    {
        _config = config;
    }

    public override IValidator CreateInstance(Type validatorType)
    {
        return (IValidator) _config.DependencyResolver.GetService(validatorType);
    }
}

WebApiConfig.cs

// throws error: instance is requested outside the context of an active (Async Scoped) scope
// FluentValidationModelValidatorProvider.Configure(GlobalConfiguration.Configuration, x => x.ValidatorFactory = container.GetInstance<IValidatorFactory>());

FluentValidationModelValidatorProvider.Configure(config, x => x.ValidatorFactory = new ServiceProviderValidatorFactory(config));

验证启动并适用于第一个API请求,但所有后续API请求都会出现The operation cannot be completed because the DbContext has been disposed.错误。

我还尝试设置ServiceProviderValidatorFactory以使用IServiceProvider方法并致电FluentValidationModelValidatorProvider.Configure(config, x => x.ValidatorFactory = new ServiceProviderValidatorFactory(container));

如下所示:

https://stackoverflow.com/a/43883455/654708

但这也不起作用。

看起来好像加载了AbstractValidator后,它们被缓存/永不丢弃,但DbContext是。{1}}。 我猜这种混合生活方式可能会起作用(因为将IReadOnlyRepository设置为单身生活方式可以正常工作)但我也没有运气。

更新

看起来好像AbstractValidator类是单身人士。我已经将验证器和工厂更新为组合根中的瞬态,但它似乎不起作用,因为它们仍然只被实例化一次。

container.Register<IValidatorFactory>(() => new ServiceProviderValidatorFactory(container), Lifestyle.Scoped);
container.Register(typeof(IValidator<>), assemblies, Lifestyle.Transient);

我已经通过在我的AbstractValidator个类中设置了一个断点来验证这一点,并且可以看到它只被调用一次,即在第一个web api请求上,而不是在后续请求中。

更新2

通过在我的Func<IReadOnlyRepository> repository类中注入AbstractValidator,我能够解决这个问题:

public class LocationModelValidator : AbstractValidator<LocationModel>
{
    public LocationModelValidator(Func<IReadOnlyRepository> repository)
    {
        // Check the database to see if this location is already present
        RuleFor(x => x.LocationId).Must(x => !repository.Invoke().Locations.Any(i => i.LocationId == x)).WithMessage("A Location with this ID already exists.");
    }
}

使用以下内容更新我的作品根目录:

container.RegisterSingleton<Func<IReadOnlyRepository>>(() => container.GetInstance<IReadOnlyRepository>);

我宁愿不必这样做,但鉴于我无法弄清楚为什么AbstractValidator总是单身,它现在会做。

0 个答案:

没有答案