SimpleInjector在.Net MVC站点启动时抛出间歇性错误

时间:2015-04-13 06:49:01

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

我有一个ASP.NET MVC,它在Application_Start方法中初始化Simple Injector。

在本地正常使用站点期间,此错误会间歇性地出现,并且在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>这是错误的来源。 IsiteManager被SimpleInjector设置为单例,这是否是问题的根源,我不确定。

具体的处理程序肯定存在(因为它实际上工作,错误是间歇性的)。

我有点难过!

这是错误和堆栈跟踪:

  

错误页面

     

无法注册IQueryHandler类型   找到。描述:期间发生了未处理的异常   执行当前的Web请求。请查看堆栈跟踪   有关错误及其来源的更多信息   码。

     

异常详细信息:SimpleInjector.ActivationException:No   注册类型IQueryHandler可能是   找到。

     

来源错误:

     

执行期间生成了未处理的异常   当前的网络请求。有关的来源和位置的信息   可以使用下面的异常堆栈跟踪来识别异常。

     

堆栈追踪:

     

[ActivationException:没有注册类型   可以找到IQueryHandler。]   SimpleInjector.Container.ThrowMissingInstanceProducerException(类型   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(关闭)+148
  SimpleInjector.Lifestyles.SingletonLifestyleRegistrationBase 1.CreateInstanceWithNullCheck() +62 System.Lazy 1.CreateValue()+415 System.Lazy 1.LazyInitValue() +152 System.Lazy 1.get_Value()+75
  SimpleInjector.Lifestyles.SingletonLifestyleRegistrationBase 1.BuildExpression() +16 SimpleInjector.Registration.BuildExpression(InstanceProducer producer) +50
SimpleInjector.InstanceProducer.BuildExpressionInternal() +34
System.Lazy
1.CreateValue()+415 System.Lazy 1.LazyInitValue() +152 System.Lazy 1.get_Value()+75
  SimpleInjector.InstanceProducer.BuildExpression()+55

     

[ActivationException:类型为ISiteManager的已注册委托   抛出一个例外。无法注册IQueryHandler类型。]
  SimpleInjector.InstanceProducer.BuildExpression()+ 97
  SimpleInjector.InstanceProducer.VerifyExpressionBuilding()+31

     

[InvalidOperationException:配置无效。创造   类型ISiteManager的实例失败。注册代表   类型ISiteManager引发了异常。没有注册类型   可以找到IQueryHandler。]   SimpleInjector.InstanceProducer.VerifyExpressionBuilding()+85
  SimpleInjector.Container.VerifyThatAllExpressionsCanBeBuilt(InstanceProducer []   producerToVerify)+28
  SimpleInjector.Container.VerifyThatAllExpressionsCanBeBuilt()+ 1277   SimpleInjector.Container.Verify()+ 109   Pipeline.CMS.UI.Client.CmsApplication.InitializeIoC()in   c:\ Projects \ Pipeline CMS \ Pipeline.CMS.UI.Client \ CmsApplication.cs:156   Pipeline.CMS.UI.Client.CmsApplication.Application_Start()in   c:\ Projects \ Pipeline CMS \ Pipeline.CMS.UI.Client \ CmsApplication.cs:47
  Pipeline.CMS.Client.MvcApplication.Application_Start()in   c:\ Projects \ Pipeline CMS \ Banerjee.Web \ Global.asax.cs:11

     

[HttpException(0x80004005):配置无效。创建   类型ISiteManager的实例失败。注册代表   类型ISiteManager引发了异常。没有注册类型   可以找到IQueryHandler。]   System.Web.HttpApplicationFactory.EnsureAppStartCalledForIntegratedMode(HttpContext的   上下文,HttpApplication app)+9936825
  System.Web.HttpApplication.RegisterEventSubscriptionsWithIIS(IntPtr的   appContext,HttpContext上下文,MethodInfo []处理程序)+118
  System.Web.HttpApplication.InitSpecial(HttpApplicationState状态,   MethodInfo [] handlers,IntPtr appContext,HttpContext context)+172
  System.Web.HttpApplicationFactory.GetSpecialApplicationInstance(IntPtr的   appContext,HttpContext context)+336
  System.Web.Hosting.PipelineRuntime.InitializeApplication(IntPtr的   appContext)+296

     

[HttpException(0x80004005):配置无效。创建   类型ISiteManager的实例失败。注册代表   类型ISiteManager引发了异常。没有注册类型   可以找到IQueryHandler。]   System.Web.HttpRuntime.FirstRequestInit(HttpContext context)+9915364   System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context)   +101 System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest)   wr,HttpContext context)+254

1 个答案:

答案 0 :(得分:3)

我的第一个直觉是,在注册过程中调用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<,>));