2015-12-08 1 views
1

Попытки внедрить данные в FluentValidation валидатор:Autofac/FluentValidation: Нет сферы с согласованием тегов «AutofacWebRequest» видна из сферы, в которой экземпляр был запрошен

public class MyFormValidator : AbstractValidator<MyForm> 
{ 
    private readonly IQueryable<Models.User> _users; 

    public MyFormValidator(IQueryable<Models.User> users) 
    { 
     _users = users; 
     ... 
    } 
} 

Моего валидатор завод:

public class DependencyResolverValidatorFactory : ValidatorFactoryBase 
{ 
    private readonly IContainer container; 

    public DependencyResolverValidatorFactory(IContainer container) 
    { 
     this.container = container; 
    } 

    public override IValidator CreateInstance(Type validatorType) 
    { 
     return container.ResolveOptionalKeyed<IValidator>(validatorType); 
    } 
} 

Мои Autofac конфигуратор:

public class AutofacConfigurator 
{ 
    public static void Configure() 
    { 
     var builder = new ContainerBuilder(); 
     ... 

     builder.RegisterType<MyFormValidator>() 
      .Keyed<IValidator>(typeof(IValidator<MyForm>)) 
      .As<IValidator>() 
      // 2nd parameter returns IQueryable<User> 
      .WithParameter("users", new SqlRepository<User>(dataContext)) 
      .InstancePerRequest(); 

     builder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource()); 

     var container = builder.Build(); 

     DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); 

     // Register the validator factory with FluentValidation, and register 
     // FluentValidation as the model validator provider for the MVC framework. 
     // see http://www.jerriepelser.com/blog/using-fluent-validation-with-asp-net-mvc-part-3-adding-dependency-injection 
     var fluentValidationModelValidatorProvider = 
      new FluentValidationModelValidatorProvider(
       new DependencyResolverValidatorFactory(container)); 
     DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false; 
     fluentValidationModelValidatorProvider.AddImplicitRequiredValidator = false; 
     ModelValidatorProviders.Providers.Add(fluentValidationModelValidatorProvider); 

    } 
} 

Получение следующей экс Цемент:

Никакой области с тегом, соответствующим «AutofacWebRequest», видны из области, в которой запрашивался экземпляр. Это обычно указывает на то, что компонент, зарегистрированный в качестве HTTP-запроса, запрашивается компонентом SingleInstance() (или аналогичным сценарием). В рамках веб-интеграции всегда запрашиваются зависимости от DependencyResolver.Current или ILifetimeScopeProvider.RequestLifetime, никогда из самого контейнера ,

У меня есть другие валидаторы, большинство из которых не нуждаются в данных, вводимых в них.

Это в значительной степени новое основание для меня (как для Autofac, так и для FluentValidation), и я все еще пытаюсь понять, что я здесь делаю. Я подозреваю, что просто зарегистрирую свой тип неправильно. Как исправить это и правильно зарегистрировать мой тип?

(Мои извинения, если это слишком похоже на другие вопросы, которые уже были заданы.)

+0

Можете ли вы показать место, где вы вызываете разрешение экземпляра валидатора? –

ответ

5

У меня есть нулевой опыт с FluentValidation, но я сомневаюсь, что это является причиной ваших проблем, во всяком случае, так что я буду пашу вперед независимо ,

Исключением, которое вы получаете, означает, что Autofac не может разрешить вашу службу как «экземпляр для запроса». Существует много документации относительно того, что это означает на странице Autofac documentation. Подводя итог, это означает, что Autofac попытается разрешить службу из области жизни, которая автоматически создается для каждого запроса, отправленного на веб-сервер. Когда вы регистрируете что-то как .InstancePerRequestScope(), но затем попытайтесь разрешить эту службу за пределами этой области, вы получите DependencyResolutionException, который вы видите.

Итак, мы установили, что ваш MyFormValidator не разрешен из области «Запрос». Зачем?

Написанный вами заказ DependencyResolverValidatorFactory содержит фактический IContainer, который был создан Autofac, и устраняет это. Это особый тип ILifetimeScope, «область корня». С этим напрямую связана область действия запроса, поэтому вы получаете свое исключение. Вам необходимо решить с ILifetimeScope, который начинается с области «запрос» или под-области, которая содержится в области запроса.

Интеграция Autofac/MVC уже автоматически содержит область запроса (в пределах AutofacDependencyResolver, см. the source), но ваш пользовательский DependencyResolverValidatorFactory не разрешает его. Если вы хотите сделать это, я полагаю, вы можете изменить свой DependencyResolverValidatorFactory, чтобы принять экземпляр AutofacDependencyResolver вместо этого и использовать его для разрешения.

Это будет выглядеть примерно так:

public class DependencyResolverValidatorFactory : ValidatorFactoryBase 
{ 
    private readonly AutofacDependencyResolver resolver; 

    public DependencyResolverValidatorFactory(AutofacDependencyResolver resolver) 
    { 
     this.resolver = resolver; 
    } 

    public override IValidator CreateInstance(Type validatorType) 
    { 
     return resolver.RequestLiftimeScope.ResolveOptionalKeyed<IValidator>(validatorType); 
    } 
} 

Обратите внимание на RequestLifetimeScope застрял там. Затем вы создаете это в методе .Configure() с помощью

var resolver = new AutofacDependencyResolver(container); 
DependencyResolver.SetResolver(resolver); 

var fluentValidationModelValidatorProvider = 
    new FluentValidationModelValidatorProvider(
     new DependencyResolverValidatorFactory(resolver)); 

Это должно избавиться от исключения, при условии, что эта фабрика действительно есть запрос на работу с момента создания экземпляров IValidator с. Если нет, возможно, вам потребуется зарегистрироваться с использованием поведения по умолчанию (.InstancePerDependency(), где он создает новый экземпляр каждый раз, когда он запрашивается) или singleton (.SingleInstance()), в зависимости от того, как или если валидаторы могут или должны использоваться совместно.

Удачи.

Смежные вопросы