是否可以在运行时更改生命周期范围?

时间:2017-12-21 09:50:55

标签: 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))
    .InstancePerRequest();

以上的作品就像魅力一样。请注意Exported

但是,现在我添加了MEF,以便我可以实现插件架构。我还添加了Autofac.Mef,以便我可以将在Autofac中注册的类型导出回MEF。

所以对于上面的Autofac配置,我还补充说:

builder.RegisterType<ImportFactory>()
    .As<IImportFactory>()
    .Exported(x => x.As<IImportFactory>())
    .InstancePerLifetimeScope();

这个工厂类只根据导入类型(例如客户,产品等)为我提供了所需的各种服务。这些服务都注册为InstancePerRequest。工厂类看起来像这样:

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();
    }
}

此外,在我的控制器中,我在一个单独的线程中启动我的导入作业,如下所示:

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();
    }
}

然而,当Autofac注入依赖项时,我现在混合了范围,因为我收到以下错误

  

无法解析类型&#39; App.Common.Logging.LogService&#39;因为它所属的生命范围无法找到。此注册公开了以下服务:    - App.Common.Logging.ILogService

     

详情---&gt;没有标记匹配的范围&#39; AutofacWebRequest&#39;从请求实例的范围可见。

     

如果在执行Web应用程序期间看到此情况,则通常表示SingleInstance()组件(或类似方案)正在请求按HTTP请求注册的组件。在Web集成下,始终从依赖项解析程序或请求生存期范围请求依赖项,而不是从容器本身请求。 (详见内部异常。)

如果所有类型都注册为InstancePerLifetimeScope,那么一切正常,即Autofac按预期注入依赖项。但问题在于类型具有不同的范围。这是因为,例如,ImportFactoryInstancePerLifetimeScope,并且它依赖于IUnitOfWork InstancePerRequest

正确的注册是什么,以便可以在不使用辅助容器和服务位置的情况下正确注入依赖项?本地范围可以做到吗?

0 个答案:

没有答案