Autofac中替代过时Update()并保留注册条件的实现方案
解决方案
一、保留条件注册逻辑(替代过时的Update()方法)
Autofac已废弃ContainerBuilder.Update(),官方推荐通过子生命周期作用域或注册时动态条件判断实现依赖实例属性的注册逻辑,以下是两种可行方案:
方案1:在IStartable中使用子作用域注册
不再修改根容器,而是在IStartable的Start方法中创建子作用域,在作用域内完成MyUi的条件注册:
public class MyUiRegistrar : IStartable { private readonly ILifetimeScope _rootScope; private readonly MyWrapper _myWrapper; public MyUiRegistrar(ILifetimeScope rootScope, MyWrapper myWrapper) { _rootScope = rootScope; _myWrapper = myWrapper; } public void Start() { if (_myWrapper.LicenseValid && _myWrapper.ManualLoadingConditions) { using (var childScope = _rootScope.BeginLifetimeScope(builder => { builder.RegisterType<MyUi>().AsSelf().SingleInstance(); })) { // 如需立即初始化MyUi,可在此解析实例 var myUi = childScope.Resolve<MyUi>(); } } } }
这种方式不修改根容器,符合Autofac设计规范,子作用域内的注册仅在该作用域生效。
方案2:注册时通过动态解析判断条件
若需要MyUi在根容器级别可用,可在Module的Load方法中用lambda表达式延迟到解析时检查条件:
public class MyModule : Module { protected override void Load(ContainerBuilder builder) { // 先注册MyWrapper实例 builder.RegisterType<MyWrapper>().SingleInstance(); // 条件满足时才创建MyUi实例 builder.Register(c => { var myWrapper = c.Resolve<MyWrapper>(); if (myWrapper.LicenseValid && myWrapper.ManualLoadingConditions) { return new MyUi(); } // 条件不满足时可返回null或抛出异常,根据业务需求调整 throw new InvalidOperationException("MyUi registration conditions not met"); }).AsSelf().SingleInstance(); } }
注:这种方式下,解析MyUi时才会校验条件;若允许MyUi不存在,可结合Optional()注册。
二、在Module中解析MyWrapper的实现方案
Module的Load方法执行时容器尚未构建,无法直接调用Resolve,可通过以下两种方式获取MyWrapper实例:
方式1:通过注册lambda延迟解析
在注册其他服务时,利用IComponentContext参数动态解析MyWrapper,如上述方案2中注册MyUi的lambda代码,通过c.Resolve<MyWrapper>()获取实例。
方式2:在AttachToComponentRegistration中解析
若需在Module中对已注册组件进行操作,可重写AttachToComponentRegistration方法,此时容器已构建完成,可直接解析实例:
public class MyModule : Module { protected override void AttachToComponentRegistration(IComponentRegistryBuilder componentRegistry, IComponentRegistration registration) { base.AttachToComponentRegistration(componentRegistry, registration); if (registration.Activator.LimitType == typeof(MyUi)) { registration.Preparing += (sender, e) => { var myWrapper = e.Context.Resolve<MyWrapper>(); // 可根据MyWrapper属性调整MyUi的创建参数 e.Parameters = e.Parameters.Union(new[] { new NamedParameter("targetParam", myWrapper.TargetProperty) }); }; } } }
这种方式适合基于MyWrapper属性动态调整其他组件创建参数的场景。
内容的提问来源于stack exchange,提问作者Paweł Urbański
相关产品推荐
相关产品推荐

