C#依赖注入:泛型工厂的抽象类型注册问题
问题根源
C#泛型默认是不变的——即使ThingA实现了IThing,IThingFactory<ThingA>也无法隐式转换为IThingFactory<IThing>,除非你将泛型接口声明为协变(适用于仅作为输出的泛型参数)。
解决方案
方案1:将泛型工厂接口改为协变
修改IThingFactory的定义,在泛型参数前添加out关键字(仅当泛型参数仅出现在返回值等输出位置时可用):
// 协变泛型工厂接口 public interface IThingFactory<out TThing> where TThing : IThing { TThing Create(); }
此时MyThingFactory<ThingA>可以直接转换为IThingFactory<IThing>,依赖注入注册代码可正常编写:
// 注册时直接绑定抽象与具体实现 services.AddSingleton<IThingFactory<IThing>, MyThingFactory<ThingA>>();
之后你就能在业务代码中注入IThingFactory<IThing>,调用Create()方法得到ThingA实例。
方案2:通过适配器/非泛型接口适配(无法修改原接口时)
如果无法修改原泛型接口的协变属性,可以新增一个非泛型的抽象工厂接口作为统一入口:
// 非泛型抽象工厂 public interface IThingFactory { IThing Create(); } // 适配器类,将泛型工厂适配为非泛型接口 public class ThingAFactoryAdapter : IThingFactory { private readonly MyThingFactory<ThingA> _innerFactory; public ThingAFactoryAdapter(MyThingFactory<ThingA> innerFactory) { _innerFactory = innerFactory; } public IThing Create() => _innerFactory.Create(); }
注册时先注册具体泛型工厂,再注册适配器:
services.AddSingleton<MyThingFactory<ThingA>>(); services.AddSingleton<IThingFactory, ThingAFactoryAdapter>();
业务代码中直接注入IThingFactory即可获取ThingA实例。
方案3:直接注册工厂委托
如果不需要额外接口,可以直接通过委托简化注册:
services.AddSingleton<IThingFactory<IThing>>(sp => new MyThingFactory<ThingA>());
内容的提问来源于stack exchange,提问作者John Freebs
相关产品推荐
相关产品推荐

