C# 是否可以在运行时更改生存期范围?
我在我的WebApi项目中使用Autofac,到目前为止一切都很好。例如,我注册:C# 是否可以在运行时更改生存期范围?,c#,asp.net-web-api,autofac,mef,C#,Asp.net Web Api,Autofac,Mef,我在我的WebApi项目中使用Autofac,到目前为止一切都很好。例如,我注册: builder.Register(x => new LogService()) .As<ILogService>().Exported(x => x.As<ILogService>()).SingleInstance(); builder.RegisterType(typeof(UnitOfWork)).As(typeof(IUnitOfWork)) .Ins
builder.Register(x => new LogService())
.As<ILogService>().Exported(x => x.As<ILogService>()).SingleInstance();
builder.RegisterType(typeof(UnitOfWork)).As(typeof(IUnitOfWork))
.InstancePerRequest();
这个工厂课程只是根据进口类型(如客户、产品等)为我提供我需要的各种服务。这些服务都注册为InstancePerRequest
。factory类如下所示:
public class ImportFactory : BaseService, IImportFactory
{
public ImportFactory(ILogService logService, IUnitOfWork unitOfWork)
: base(logService, unitOfWork) { }
}
[Export(typeof(IImportPlugin))]
public class ImportCustomers : ImportPlugin, IImportPlugin
{
private ICustomerService customerService;
[ImportingConstructor]
public ImportCustomers(ILogService logService, IImportFactory importFactory)
: base()
{
this.logService = logService;
this.importFactory = importFactory;
}
}
这些插件如下所示:
public class ImportFactory : BaseService, IImportFactory
{
public ImportFactory(ILogService logService, IUnitOfWork unitOfWork)
: base(logService, unitOfWork) { }
}
[Export(typeof(IImportPlugin))]
public class ImportCustomers : ImportPlugin, IImportPlugin
{
private ICustomerService customerService;
[ImportingConstructor]
public ImportCustomers(ILogService logService, IImportFactory importFactory)
: base()
{
this.logService = logService;
this.importFactory = importFactory;
}
}
每个插件都有一个模块,可以在Autofac中注册:
[Export(typeof(IModule))]
public class AutofacModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<ImportCustomers>()
.Exported(x => x.As<IImportPlugin>())
.InstancePerLifetimeScope();
}
}
[Export(typeof(IModule))]
公共类自动传真模块:模块
{
受保护的覆盖无效负载(ContainerBuilder builder)
{
builder.RegisterType()
.Exported(x=>x.As())
.InstancePerLifetimeScope();
}
}
此外,从控制器内部,我在单独的线程中启动导入作业,如下所示:
public class ImportController : BaseController
{
private readonly IComponentContext componentContext;
public ImportController(IComponentContext componentContext, ILogService logService)
: base(logService)
{
this.componentContext = componentContext;
}
public IHttpActionResult Start()
{
var config = componentContext.Resolve<IPluginConfig>();
var plugins = config.ImportPlugins;
HostingEnvironment.QueueBackgroundWorkItem(ct =>
{
plugins.First().Import(); //Just to test
});
return Ok();
}
}
<代码>公共类ImportControl ler:BaseController
{
私有只读IComponentContext组件上下文;
公共导入控制器(IComponentContext组件上下文,ILogService日志服务)
:基本(后勤服务)
{
this.componentContext=componentContext;
}
公共IHttpActionResult开始()
{
var config=componentContext.Resolve();
var plugins=config.ImportPlugins;
HostingEnvironment.QueueBackgroundWorkItem(ct=>
{
plugins.First().Import();//仅用于测试
});
返回Ok();
}
}
但是现在,当Autofac注入依赖项时,我有一个混合作用域,因为我得到以下错误
无法解析类型“App.Common.Logging.LogService”,因为找不到它所属的生存期作用域。此注册公开了以下服务:
-App.Common.Logging.ILogService
详细信息--->从请求实例的作用域中看不到标记与“AutofacWebRequest”匹配的作用域
如果您在web应用程序的执行过程中看到这一点,通常表示SingleInstance()组件(或类似场景)正在请求按照HTTP请求注册的组件。在web集成下,始终从依赖项解析器或请求生存期范围请求依赖项,而不是从容器本身。(有关详细信息,请参见内部异常。)
如果所有类型都注册为InstancePerLifetimeScope
,则一切正常,即Autofac按预期注入依赖项。但是,问题在于类型的作用域不同。这是因为,例如,ImportFactory
是InstancePerLifetimeScope
,它依赖于IUnitOfWork
,即InstancePerRequest
什么是正确的注册,以便在不使用辅助容器和服务位置的情况下正确注入依赖项?本地示波器会起作用吗?你有吗?Autofac.Mef将Mef组件引入Autofac,而不是相反。@TravisIllig是的,我读过它们,我几乎成功地使其工作。我在每个MEF插件中添加了一个Autofac模块,允许它向容器注册其类型。我遇到的问题与不同的作用域有关,我无法解决它,因为代码是固定的。@TravisIllig如果所有类型都注册为
InstancePerLifetimeScope
,那么它就工作了。然而,我认为这不是正确的解决方案,因为我宁愿在ILogService
上使用SingleInstance
,在工作单元和所有服务上使用InstancePerRequest
。“我还添加了Autofac.Mef,这样我就可以将在Autofac中注册的类型导出回Mef。”这就是我挂断电话的地方。如果你想走这条路,你会很难过的。另外,您是否尝试过不在QueueBackgroundWorkItem
中导入插件?分离线程表示“可能在当前请求之外执行”,对吗?在控制器中,什么是componentContext
?为什么选择服务位置而不是DI?(更新代码和要解释的问题。)