如何在Autofac中解析目标类时向其依赖传递运行时参数?
问题描述
我使用Autofac作为IoC容器,希望在解析时传递参数,但参数并非传给调用Resolve方法的类,而是传给解析树中的依赖。
假设有以下类结构:
public interface IService { } public class Service : IService{ public Service(ILogger logger){ } } public interface ILogger { } public class Logger : ILogger{ public Logger (LoggerConfig options){ } }
按照Autofac文档创建容器的代码如下:
public static IContainer CreateContainer(){ var builder = new ContainerBuilder(); builder.RegisterType<Service>().As<IService>(); builder.Register<Logger>((c, p) => new Logger(p.AsTyped<LoggerConfig>())).As<ILogger>(); return builder.Build(); }
我发现若要为ILogger传递解析参数,必须先解析ILogger,而非直接解析我需要的IService。
如下方式无法生效:
var container = CreateContainer(); container.Resolve<IService>(new TypedParameter(typeof(LoggerConfig), new LoggerConfig()));
必须先执行以下操作才能生效:
var container = CreateContainer(); container.Resolve<ILogger>(new TypedParameter(typeof(LoggerConfig), new LoggerConfig())); container.Resolve<IService>();
请问:如何在解析目标类时,向其依赖传递运行时参数?
解决方案
要在解析IService时直接给依赖的ILogger传递运行时参数,有两种可靠的实现方式:
方式一:使用ResolvedParameter精准匹配依赖
在调用Resolve<IService>时,用ResolvedParameter指定参数要传递给哪个具体的依赖类型,而非仅传递TypedParameter。
修改调用代码如下:
var container = CreateContainer(); var config = new LoggerConfig(); // 定义参数:当构造函数参数类型是LoggerConfig,且所属类型是Logger时,使用指定的config var param = new ResolvedParameter( (pi, ctx) => pi.ParameterType == typeof(LoggerConfig) && pi.Member.DeclaringType == typeof(Logger), (pi, ctx) => config ); var service = container.Resolve<IService>(param);
这种方式能精准定位参数的目标依赖,避免参数被其他可能依赖LoggerConfig的类误获取。
方式二:注册时确保参数向下传递
修改Logger的注册逻辑,让它从解析上下文的参数集合中获取配置,Autofac会自动将上层解析IService时传入的参数传递到依赖链中。
修改容器注册代码:
public static IContainer CreateContainer(){ var builder = new ContainerBuilder(); builder.RegisterType<Service>().As<IService>(); // 从解析参数中提取LoggerConfig,若需容错可添加默认值逻辑 builder.Register<Logger>((c, p) => { var config = p.TypedAs<LoggerConfig>(); return new Logger(config); }).As<ILogger>(); return builder.Build(); }
之后直接调用Resolve<IService>并传递参数即可生效:
var container = CreateContainer(); var service = container.Resolve<IService>(new TypedParameter(typeof(LoggerConfig), new LoggerConfig()));
注意事项
- 不要依赖先解析
ILogger再解析IService的方式,这会导致容器缓存的ILogger实例被后续所有IService复用,若LoggerConfig是动态变化的,会引发逻辑错误。 - 如果
LoggerConfig是全局通用配置,更推荐在注册阶段直接将其注册为单例,而非每次解析都传递参数。
内容的提问来源于stack exchange,提问作者JuanDYB
相关产品推荐
相关产品推荐

