SimpleInjector выдает прерывистую ошибку при запуске сайта .Net MVC

У меня есть ASP.NET MVC, который инициализирует Simple Injector в методе Application_Start.

Ошибка периодически появляется при обычном локальном использовании сайта и всегда исчезает при перестроении сайта в Visual Studio. При развертывании ошибка появляется сразу, но ее можно устранить, перезапустив приложение на сервере. Через некоторое время снова появляется.

Код запуска следующий:

public class CmsApplication : System.Web.HttpApplication
{
    private Container _container;
    private IQueryProcessor queryProcessor;

    private static ISiteManager _manager;
    public static ISiteManager SiteManager { get { return _manager; } }

    protected virtual void Application_Start()
    {
        // Mapping using AutoMapper
        CMS.UI.Client.Mapping.MappingConfig.RegisterMappings();

        // Initialize SimpleInjector
        InitializeIoC();

        AutoMapper.Mapper.AssertConfigurationIsValid();

        // Get query processor - this is used for handling database calls.
        queryProcessor = _container.GetInstance<IQueryProcessor>();

        // Get configuration
        IConfiguration configuration = CMS.Configuration.ConfigurationFactory.Get();

        // MVC Stuff
        AreaRegistration.RegisterAllAreas();
        RouteConfig routeConfig = new RouteConfig(queryProcessor);
        routeConfig.RegisterRoutes(RouteTable.Routes);

        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);

        // Regular MVC startup
        AreaRegistration.RegisterAllAreas();

        // Global SiteManager property. THIS COULD BE CAUSING THE ISSUE!
        _manager = _container.GetInstance<ISiteManager>();

    }

    /// <summary>
    /// Method to initialize the IoC Container
    /// </summary>
    protected void InitializeIoC()
    {
        // Initialize DI container
        _container = new Container();

        // Allows container to inject into filter constructors
        _container.RegisterMvcIntegratedFilterProvider();

        // Mapping
        _container.Register<AutoMapper.IMappingEngine>(() => (AutoMapper.IMappingEngine)AutoMapper.Mapper.Engine, Lifestyle.Singleton);
        _container.Register<IMapProcessor, MapProcessor>(); // Map Processor

        // Configuration
        _container.Register<IConfiguration>(() => (CMS.Configuration.Configuration)System.Configuration.ConfigurationManager.GetSection("pipeline"), Lifestyle.Singleton);

        // Site Manager
        _container.Register<ISiteManager, SiteManager>(Lifestyle.Singleton);

        // Context and UnitOfWork Factories
        _container.RegisterPerWebRequest<IContext>(() => new CrmContext("Name=CrmContext"));

        // Context and UnitOfWork     
        _container.RegisterPerWebRequest<Pipeline.Core.Data.UnitOfWork.IUnitOfWork, Crm.UnitOfWork.EFUnitOfWork>();

        // Repositories
        _container.Register<ISiteRepository, SiteRepository>();
        _container.Register<IFolderRepository, FolderRepository>();

        // Sitemap
        _container.Register<ISitemapGenerator, SitemapGenerator>();

        // Robots
        _container.Register<IRobotsGenerator, RobotsGenerator>();

        // Command Handlers
        _container.RegisterOpenGeneric(
            typeof(IBatchCommandHandler<>), typeof(BatchCommandHandler<>));

        _container.RegisterManyForOpenGeneric(
            typeof(ICommandHandler<>),
            AppDomain.CurrentDomain.GetAssemblies());

        _container.RegisterManyForOpenGeneric(
            typeof(ICommandHandler<,>),
            AppDomain.CurrentDomain.GetAssemblies());

        // Validators
        _container.RegisterManyForOpenGeneric(
            typeof(IValidator<>),
            AppDomain.CurrentDomain.GetAssemblies());

        // Query Handlers
        _container.RegisterManyForOpenGeneric(
            typeof(IQueryHandler<,>),
            AppDomain.CurrentDomain.GetAssemblies());

        // Query Processor
        _container.Register<IQueryProcessor>(() => new QueryProcessor(_container));

        // Validation Decorators
        _container.RegisterDecorator(typeof(ICommandHandler<,>),
            typeof(ValidationCommandHandlerDecorator<,>),
            c => typeof(ICommandHandler<,>)
                    .MakeGenericType(c.ServiceType.GetGenericArguments())
                        .IsAssignableFrom(c.ImplementationType));


                    // Verify the container
        _container.Verify();

        //// Register the container as MVC IDependencyResolver
        DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(_container));

    }

Метод InitializeIoC — это просто регистрация различных типов и ничего особенного.

После метода InitializeIoC вызов RouteConfig использует вызов базы данных с использованием типа, разрешенного с помощью SimpleInjector. Кажется, это нормально.

Кажется, что ошибка возникает, когда поле _manager установлено, поскольку разрешенный тип использует IQueryHandler<SiteQuery, ISiteInfo>, который является источником ошибки. SimpleInjector устанавливает ISiteManager как синглтон, является ли это источником проблемы, я не уверен.

Конкретный обработчик определенно присутствует (поскольку он действительно работает, ошибка прерывистая).

Я немного озадачен этим!

Вот ошибка и трассировка стека:

Страница ошибки

Не удалось найти регистрацию для типа IQueryHandler. Описание: во время выполнения текущего веб-запроса возникло необработанное исключение. Пожалуйста, просмотрите трассировку стека для получения дополнительной информации об ошибке и о том, где она возникла в коде.

Сведения об исключении: SimpleInjector.ActivationException: не удалось найти регистрацию для типа IQueryHandler.

Ошибка источника:

Во время выполнения текущего веб-запроса возникло необработанное исключение. Информацию о происхождении и расположении исключения можно определить с помощью приведенной ниже трассировки стека исключений.

Трассировки стека:

[ActivationException: не удалось найти регистрацию для типа IQueryHandler.]
SimpleInjector.Container.ThrowMissingInstanceProducerException(Type serviceType) +136 SimpleInjector.Container.GetInstance(Type serviceType) +76
Pipeline.Crm.Services.QueryProcessor.QueryProcessor .Pipeline.Core.Services.Queries.Interfaces.IQueryProcessor.Process(запрос IQuery) в c:\Projects\Pipeline CMS\Pipeline.CMS.Services\QueryProcessor\QueryProcessor.cs:29
Pipeline.CMS.UI.Client .Management.SiteManager..ctor(IQueryProcessor queryProcessor, конфигурация IConfiguration) в c:\Projects\Pipeline CMS\Pipeline.CMS.UI.Client\SiteManager\SiteManager.cs:23
lambda_method(Closure) +148
SimpleInjector.Lifestyles.SingletonLifestyleRegistrationBase1.CreateInstanceWithNullCheck() +62 System.Lazy1.CreateValue() +415 System.Lazy1.LazyInitValue() +152 System.Lazy1.get_Value() +75
SimpleInjector.Lifestyles.SingletonLifestyleRegistrationBase1.BuildExpression() +16 SimpleInjector.Registration.BuildExpression(InstanceProducer producer) +50
SimpleInjector.InstanceProducer.BuildExpressionInternal() +34
System.Lazy
1.CreateValue() +415 System.Lazy1.LazyInitValue() +152 System.Lazy1.get_Value() +75
SimpleInjector.InstanceProducer. BuildE выражение() +55

[ActivationException: зарегистрированный делегат для типа ISiteManager вызвал исключение. Не удалось найти регистрацию для типа IQueryHandler.]
SimpleInjector.InstanceProducer.BuildExpression() +97
SimpleInjector.InstanceProducer.VerifyExpressionBuilding() +31

[InvalidOperationException: конфигурация недействительна. Не удалось создать экземпляр для типа ISiteManager. Зарегистрированный делегат для типа ISiteManager вызвал исключение. Не удалось найти регистрацию для типа IQueryHandler.]
SimpleInjector.InstanceProducer.VerifyExpressionBuilding() +85
SimpleInjector.Container.VerifyThatAllExpressionsCanBeBuilt(InstanceProducer[] productsToVerify) +28
SimpleInjector.Container.VerifyThatAllExpressionsCanBeBuilt() +127
SimpleInjector.Container.Verify() +109
Pipeline.CMS.UI.Client.CmsApplication.InitializeIoC() в c:\Projects\Pipeline CMS\Pipeline.CMS.UI.Client\CmsApplication.cs:156 Pipeline.CMS.UI.Client.CmsApplication.Application_Start() в c:\Projects\Pipeline CMS\Pipeline.CMS.UI.Client\CmsApplication.cs:47
Pipeline.CMS.Client.MvcApplication.Application_Start() в c:\Projects\Pipeline CMS\Banerjee.Web\Global.asax.cs:11

[HttpException (0x80004005): конфигурация недействительна. Не удалось создать экземпляр для типа ISiteManager. Зарегистрированный делегат для типа ISiteManager вызвал исключение. Не удалось найти регистрацию для типа IQueryHandler.]
System.Web.HttpApplicationFactory.EnsureAppStartCalledForIntegratedMode(контекст HttpContext, приложение HttpApplication) +9936825
System.Web.HttpApplication.RegisterEventSubscriptionsWithIIS(IntPtr appContext, контекст HttpContext, обработчики MethodInfo[] ) +118
System.Web.HttpApplication.InitSpecial(состояние HttpApplicationState, обработчики MethodInfo[], IntPtr appContext, контекст HttpContext) +172
System.Web.HttpApplicationFactory.GetSpecialApplicationInstance(IntPtr appContext, контекст HttpContext) +336< br> System.Web.Hosting.PipelineRuntime.InitializeApplication(IntPtr appContext) +296

[HttpException (0x80004005): конфигурация недействительна. Не удалось создать экземпляр для типа ISiteManager. Зарегистрированный делегат для типа ISiteManager вызвал исключение. Не удалось найти регистрацию для типа IQueryHandler.]
System.Web.HttpRuntime.FirstRequestInit(контекст HttpContext) +9915364 System.Web.HttpRuntime.EnsureFirstRequestInit(контекст HttpContext) +101 System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, Контекст HttpContext) +254


person Graham    schedule 13.04.2015    source источник


Ответы (1)


Моя первая интуиция заключается в том, что сборка, содержащая реализации обработчика запросов, еще не загружена в то время, когда AppDomain.CurrentDomain.GetAssemblies() вызывается в процессе регистрации. Ваши реализации обработчика запросов, вероятно, находятся в другой сборке, чем интерфейс IQueryHandler<,>. Загрузка сборок может быть немного недетерминированной в ASP.NET.

Вместо вызова AppDomain.CurrentDomain.GetAssemblies() попробуйте указать сборки напрямую следующим образом:

var assemblies = new[]
{
    typeof(SomeQueryHandlerImplementation).Assembly,
    typeof(SqlRepository<>).Assembly,
};

// Simple Injector v3.x
_container.Register(typeof(ICommandHandler<>), assemblies);
_container.Register(typeof(ICommandHandler<,>), assemblies);
_container.Register(typeof(IValidator<>), assemblies);
_container.Register(typeof(IQueryHandler<,>), assemblies);

// Simple Injector v2.x
_container.RegisterManyForOpenGeneric(typeof(ICommandHandler<>), assemblies);
_container.RegisterManyForOpenGeneric(typeof(ICommandHandler<,>), assemblies);
_container.RegisterManyForOpenGeneric(typeof(IValidator<>), assemblies);
_container.RegisterManyForOpenGeneric(typeof(IQueryHandler<,>), assemblies);

Одно небольшое замечание по поводу регистрации декоратора ValidationCommandHandlerDecorator. Зарегистрированный предикат всегда возвращает true. Таким образом, регистрацию можно упростить до следующего:

_container.RegisterDecorator(typeof(ICommandHandler<,>),
    typeof(ValidationCommandHandlerDecorator<,>));
person Steven    schedule 13.04.2015