如何在Autofac中创建动态工厂以注册依赖容器服务的适配器
在Autofac中注册依赖容器的动态适配器工厂
你遇到的场景很典型——遗留代码限制了适配器架构的修改,但又需要让适配器能获取Autofac容器中的依赖。其实不用直接依赖IContainer,Autofac提供了更优雅的方式:利用IComponentContext(容器解析上下文)来动态获取依赖,同时保持你的适配器封装逻辑不变。
下面是具体的实现方案:
核心思路
Autofac的Register方法允许你传入一个Func<IComponentContext, T>委托,这个委托会在服务被解析时执行,你可以通过IComponentContext来获取任何已注册的依赖。这样就能避免提前实例化适配器,而是在需要的时候动态创建并注入所需的依赖。
修改后的注册方法
首先调整你的RegisterAdaptableInstance方法,让它支持通过容器上下文解析依赖:
protected void RegisterAdaptableInstance<TEntity, TDTO, TOptions>( ContainerBuilder builder, Func<IComponentContext, TOptions, TDTO> adaptFunc) where TOptions : IToDTOAdapterOptions<TEntity> { // 注册一个委托,在解析时创建ToDTOAdaptable实例,并传入带上下文的适配逻辑 builder.Register(ctx => new ToDTOAdaptable<TEntity, TDTO, TOptions>(options => adaptFunc(ctx, options))) .As<IToDTOAdaptable<TEntity, TDTO, IToDTOAdapterOptions<TEntity>>>() .SingleInstance(); // 如果适配逻辑本身无状态,保持单例没问题 }
具体注册示例
现在你可以在注册适配器时,轻松获取容器中的依赖(比如MyDBContext):
protected void RegisterAdaptables(ContainerBuilder builder) { // 注册需要MyDBContext的适配器 this.RegisterAdaptableInstance<IOnboardingTask, OnboardingTaskDTO, IToDTOAdapterOptions<IOnboardingTask>>( builder, (ctx, options) => { // 从容器上下文解析MyDBContext var dbContext = ctx.Resolve<MyDBContext>(); // 创建适配器并执行转换 return new OnboardingTaskGetterAdapter(dbContext, options.Entity).ToDTO(); }); }
为什么用IComponentContext而不是IContainer?
IComponentContext是当前的解析上下文,支持嵌套容器、作用域等场景,比直接依赖根容器IContainer更灵活。- 遵循Autofac的最佳实践,避免直接引用根容器,减少耦合。
额外说明
如果你的ToDTOAdaptable类本身需要依赖,也可以通过ctx.Resolve来获取,完全适配复杂的依赖场景。而且这种方式不需要修改任何遗留的适配器代码,完美符合你的限制条件。
内容的提问来源于stack exchange,提问作者johnny 5
相关产品推荐
相关产品推荐

