Autofac注册同一类多实例时参数值共享,如何解决?
问题原因与解决方案
问题原因
你遇到的问题是因为Autofac注册时,两次调用As<IPreferencesRetriever>()会导致第二个注册覆盖第一个的默认IPreferencesRetriever服务。虽然你添加了Keyed标识,但每个注册同时被标记为默认服务,Autofac会将最后一次注册的实例作为默认实现,进而导致即使通过KeyFilter解析,也会出现实例混淆的情况;另外也可能是构造函数参数匹配失败,回退到了默认服务实例。
解决方案
1. 修改Autofac注册方式,移除默认服务注册
去掉As<IPreferencesRetriever>(),仅保留Keyed标识,确保两个单例实例完全独立,仅通过Key来解析:
using Autofac; using Autofac.Extensions.DependencyInjection; public void ConfigureContainer(ContainerBuilder builder) { // Preferences builder.RegisterType<PreferencesRetriever>() .Keyed<IPreferencesRetriever>("PreferencesRetriever") .SingleInstance() .WithParameter("collection", _configureMongo(_mongoUrl, MONGODB_PREFERENCES_COLLECTION)); // System Preferences builder.RegisterType<PreferencesRetriever>() .Keyed<IPreferencesRetriever>("SystemPreferencesRetriever") .SingleInstance() .WithParameter("collection", _configureMongo(_mongoUrl, MONGODB_SYSTEM_PREFERENCES_COLLECTION)); }
2. 验证构造函数参数匹配
确保PreferencesRetriever的构造函数中,集合参数的名称确实是collection。如果参数名称不同(例如mongoCollection),WithParameter("collection", ...)会匹配失败,导致注入默认服务实例。如果参数名称不匹配,改用按类型匹配:
.WithParameter(new TypedParameter(typeof(IMongoCollection<YourPreferenceType>), _configureMongo(_mongoUrl, MONGODB_PREFERENCES_COLLECTION)))
3. 确认_configureMongo返回独立实例
检查_configureMongo方法,确保传入不同集合名称时返回不同的IMongoCollection实例。可以在注册时添加日志输出集合名称,验证两次调用的结果:
var prefCollection = _configureMongo(_mongoUrl, MONGODB_PREFERENCES_COLLECTION); Console.WriteLine($"Preferences collection: {prefCollection.CollectionNamespace.CollectionName}"); var systemPrefCollection = _configureMongo(_mongoUrl, MONGODB_SYSTEM_PREFERENCES_COLLECTION); Console.WriteLine($"System Preferences collection: {systemPrefCollection.CollectionNamespace.CollectionName}");
4. 修复控制器日志类型(非核心但建议)
SystemPreferencesController中的ILogger泛型参数错误,应该对应自身控制器类型:
public SystemPreferencesController( [KeyFilter("SystemPreferencesRetriever")] IPreferencesRetriever preferencesRetriever, ILogger<SystemPreferencesController> logger) // 改为SystemPreferencesController { _preferencesRetriever = preferencesRetriever; _logger = logger; }
内容的提问来源于stack exchange,提问作者jtmaps
相关产品推荐
相关产品推荐

