.NET6 C#:如何通过工厂方法从依赖注入返回单例MyClass实例
解决方案:在.NET6中通过DI注册并获取不同构造参数的MyClass单例
直接两次调用AddSingleton<MyClass>会导致后一次注册覆盖前一次,因为DI容器中同一类型的注册默认会被后续项覆盖。要实现同时存在两个不同构造参数的MyClass单例,你可以用以下两种原生.NET6方案:
方案一:用包装类区分实例(最直观的原生实现)
通过定义轻量包装类,让DI容器区分不同构造参数的MyClass实例:
- 定义包装类
// 包装依赖IMyInterface1的MyClass实例 public class MyClassWithInterface1 { public MyClass Instance { get; } public MyClassWithInterface1(IMyInterface1 dependency) { Instance = new MyClass(dependency); } } // 包装依赖IMyInterface2的MyClass实例 public class MyClassWithInterface2 { public MyClass Instance { get; } public MyClassWithInterface2(IMyInterface2 dependency) { Instance = new MyClass(dependency); } }
- 注册包装类为单例
在Program.cs中注册这两个包装类,它们内部的MyClass会自动成为单例:
builder.Services.AddSingleton<MyClassWithInterface1>(); builder.Services.AddSingleton<MyClassWithInterface2>();
- 修改工厂类
注入包装类并直接取出内部的MyClass单例:
public class MyClassFactory { private readonly MyClass _instanceWithInterface1; private readonly MyClass _instanceWithInterface2; public MyClassFactory(MyClassWithInterface1 wrapper1, MyClassWithInterface2 wrapper2) { _instanceWithInterface1 = wrapper1.Instance; _instanceWithInterface2 = wrapper2.Instance; } public MyClass GetMyClass(bool condition) { return condition ? _instanceWithInterface1 : _instanceWithInterface2; } }
- 确保工厂类为单例
builder.Services.AddSingleton<MyClassFactory>();
方案二:用字典存储命名实例(更灵活的方式)
直接在DI中注册一个包含两个MyClass单例的字典,通过键名区分:
- 注册字典单例
在Program.cs中创建并注册包含两个实例的字典:
builder.Services.AddSingleton<IDictionary<string, MyClass>>(sp => { return new Dictionary<string, MyClass> { ["Interface1"] = new MyClass(sp.GetRequiredService<IMyInterface1>()), ["Interface2"] = new MyClass(sp.GetRequiredService<IMyInterface2>()) }; });
- 修改工厂类
注入字典并根据条件返回对应实例:
public class MyClassFactory { private readonly IDictionary<string, MyClass> _myClassInstances; public MyClassFactory(IDictionary<string, MyClass> myClassInstances) { _myClassInstances = myClassInstances; } public MyClass GetMyClass(bool condition) { return condition ? _myClassInstances["Interface1"] : _myClassInstances["Interface2"]; } }
关键说明
- 无论哪种方案,工厂类都是单例,注入到作用域服务后,每次调用
GetMyClass返回的都是预先创建好的MyClass单例,不会随作用域服务重建而新建。 - 若后续升级到.NET7+,可以使用原生键控服务(Keyed Services),写法会更简洁,但.NET6不支持该特性。
内容的提问来源于stack exchange,提问作者CodeMonkey
相关产品推荐
相关产品推荐

