Autofac:解析后通过OnActivated/OnActivating获取构造函数参数
解决Autofac中自动调用Service.SetViewModel的问题
你可以通过工厂注册方式或者批量激活回调来实现这个需求,不需要在每个ViewModel里手动调用service.SetViewModel(this)。下面分两种场景给出具体方案:
1. 单个ViewModel的简单实现
如果只需要处理少数几个ViewModel,直接用Autofac的工厂注册方式最直接,而且能保证使用构造函数注入的同一个Service实例:
builder.Register(c => { // 从Autofac容器解析出所需的SomeService var service = c.Resolve<SomeService>(); // 创建ViewModel实例 var viewModel = new SomeViewModel(service); // 自动调用SetViewModel方法 service.SetViewModel(viewModel); return viewModel; }).AsSelf();
这种方式不需要修改你现有的ViewModel代码,完全把关联逻辑放到了IoC容器配置里。
2. 多个ViewModel的批量处理
如果有大量ViewModel都需要类似的关联操作,推荐通过接口约束+反射批量处理,避免重复代码:
第一步:定义统一接口
先创建一个通用接口,让所有需要关联Service的ViewModel实现它:
public interface IServiceBoundViewModel<TService> { // 暴露注入的Service供Autofac调用 TService BoundService { get; } }
第二步:修改ViewModel实现接口
更新你的ViewModel,保存注入的Service并实现接口:
class SomeViewModel : IServiceBoundViewModel<SomeService> { public SomeService BoundService { get; } public SomeViewModel(SomeService service) { BoundService = service; // 移除手动调用的service.SetViewModel(this) } }
第三步:Autofac批量注册配置
通过反射扫描所有实现了该接口的ViewModel,统一添加激活回调:
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()) // 筛选出所有实现了IServiceBoundViewModel<T>的类型 .Where(t => t.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IServiceBoundViewModel<>))) .AsSelf() .OnActivated(e => { var vmInstance = e.Instance; // 获取ViewModel实现的泛型接口 var interfaceType = vmInstance.GetType() .GetInterfaces() .First(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IServiceBoundViewModel<>)); // 获取Service类型和BoundService属性 var serviceType = interfaceType.GetGenericArguments()[0]; var serviceProperty = interfaceType.GetProperty(nameof(IServiceBoundViewModel<object>.BoundService)); if (serviceProperty != null) { var service = serviceProperty.GetValue(vmInstance); // 调用Service的SetViewModel方法 var setViewModelMethod = serviceType.GetMethod(nameof(SomeService.SetViewModel)); setViewModelMethod?.Invoke(service, new[] { vmInstance }); } });
这样所有实现了IServiceBoundViewModel<T>的ViewModel都会在被Autofac创建后,自动调用对应Service的SetViewModel方法,完全不需要手动编写关联代码。
为什么OnActivated直接解析Service不可靠?
你之前尝试的OnActivated如果直接用e.Context.Resolve<SomeService>(),如果SomeService是**瞬态(Transient)**生命周期,会得到一个新的Service实例,和构造函数注入的不是同一个,导致关联逻辑失效。而上面的工厂方法或者接口约束的方式,都是使用ViewModel构造时注入的同一个Service实例,避免了这个问题。
内容的提问来源于stack exchange,提问作者Winetradr
相关产品推荐
相关产品推荐

