我有一个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:否
IQueryHandler类型的注册可能是
找到了。
源错误:
执行过程中产生了未处理的异常
当前的Web请求。有关原产地和位置的信息
可以使用下面的异常堆栈跟踪来识别异常。
堆栈跟踪:
[ActivationException:没有注册类型
可以找到IQueryHandler。]
SimpleInjector.Container.ThrowMissingInstanceProducerException(Type
serviceType)+136 SimpleInjector.Container.GetInstance(类型
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
c:\ Projects \ Pipeline中的queryProcessor,IConfiguration配置)
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()+75SimpleInjector.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()+75SimpleInjector.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 []
producersVerify)+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
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
最佳答案
我的第一个直觉是,在注册过程中调用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<,>));