如何通过Autofac获取IConsumerHandler<ISpecificRecord>的所有实现集合?
Autofac获取泛型接口所有实现集合的解决方案
Autofac默认不直接支持注入IEnumerable<IConsumerHandler<ISpecificRecord>>,核心原因是你的泛型接口IConsumerHandler<T>未声明为协变接口,Autofac无法将IConsumerHandler<CreateSubscription>(封闭泛型类型)视为IConsumerHandler<ISpecificRecord>的兼容类型。
以下是两种可行的解决办法:
方案一:修改接口为协变泛型接口
如果业务场景允许,给泛型接口添加out关键字声明协变(要求接口中T仅用作输出参数/返回值,不能作为输入参数类型):
public interface IConsumerHandler<out T> where T : ISpecificRecord { string TopicName { get; set; } event EventHandler MessageObtained; void OnMessageObtained(GenericEventArgs<T> e); }
修改后,原注册代码无需改动,直接在服务构造函数中注入IEnumerable<IConsumerHandler<ISpecificRecord>>即可获取所有实现类实例。
方案二:不修改接口,调整注册逻辑
如果无法修改接口,可在注册时主动将每个实现类同时注册为IConsumerHandler<ISpecificRecord>类型:
简化版注册
builder.RegisterAssemblyTypes(assemblies) .AsClosedTypesOf(typeof(IConsumerHandler<>)) .As(typeof(IConsumerHandler<ISpecificRecord>)) .AsImplementedInterfaces();
精确版注册(避免类型误匹配)
// 遍历程序集中所有符合条件的实现类 foreach (var type in assemblies.SelectMany(a => a.GetTypes()) .Where(t => !t.IsAbstract && !t.IsInterface && t.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IConsumerHandler<>)))) { // 获取实现的封闭泛型接口 var closedInterface = type.GetInterfaces() .First(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IConsumerHandler<>)); // 同时注册为封闭泛型接口和IConsumerHandler<ISpecificRecord> builder.RegisterType(type) .As(closedInterface) .As(typeof(IConsumerHandler<ISpecificRecord>)) .AsImplementedInterfaces(); }
验证方式
在目标服务的构造函数中注入集合:
public class ConsumerManager { public ConsumerManager(IEnumerable<IConsumerHandler<ISpecificRecord>> allHandlers) { // allHandlers将包含所有实现IConsumerHandler<T>的实例 foreach (var handler in allHandlers) { Console.WriteLine($"Loaded handler for topic: {handler.TopicName}"); } } }
内容的提问来源于stack exchange,提问作者Qhori
相关产品推荐
相关产品推荐

