如何通过DI容器动态创建带构造参数的指定类型对象实例
解决DI容器中动态解析带构造参数的对象问题
实现方案
要实现根据传入类型动态解析对象并传递document构造参数,无需手动实例化对象,可利用ActivatorUtilities.CreateInstance方法结合DI容器完成。这个方法会自动从容器中获取类型所需的依赖,同时接受你传入的动态参数(这里就是document)。
修改后的核心代码
重点修改Program中IObjectFactory的注册逻辑:
services.AddSingleton<IObjectFactory>(sp => { return new ObjectFactory((document, type) => { // 从DI容器解析对应类型实例,并传入document参数 return (IObject)ActivatorUtilities.CreateInstance(sp, type, document); }); });
完整修改后的代码
namespace ConsoleApp9 { public interface IObjectFactory { IObject Create(IDocument document, int type); } public class ObjectFactory : IObjectFactory { private readonly Func<IDocument, Type, IObject> _factory; public ObjectFactory(Func<IDocument, Type, IObject> factory) { _factory = factory; } public IObject Create(IDocument document, int type) { if (type == 0) return _factory(document, typeof(IObject1)); if (type == 1) return _factory(document, typeof(IObject2)); throw new NotSupportedException(nameof(type)); } } public interface IDocument { void CreateObject(int type); } public class Document : IDocument { private readonly IObjectFactory _objectFactory; public List<IObject> Objects { get; } = new(); public Document(IObjectFactory objectFactory) { _objectFactory = objectFactory; } public void CreateObject(int type) { var obj = _objectFactory.Create(this, type); Objects.Add(obj); } } public interface IObject { IDocument Document { get; } } public interface IObject1 : IObject { } public class Object1 : IObject1 { public IDocument Document { get; } public Object1(IDocument document) { Document = document; } } public interface IObject2 : IObject { } public class Object2 : IObject2 { public IDocument Document { get; } public Object2(IDocument document) { Document = document; } } internal class Program { static void Main(string[] args) { var services = new ServiceCollection(); services.AddTransient<IObject1, Object1>(); services.AddTransient<IObject2, Object2>(); // 修改后的工厂注册逻辑 services.AddSingleton<IObjectFactory>(sp => { return new ObjectFactory((document, type) => { return (IObject)ActivatorUtilities.CreateInstance(sp, type, document); }); }); services.AddTransient<IDocument, Document>(); var serviceProvider = services.BuildServiceProvider(); var document = serviceProvider.GetRequiredService<IDocument>(); document.CreateObject(0); document.CreateObject(1); } } }
原理说明
ActivatorUtilities.CreateInstance会先检查目标类型的构造函数,优先使用你传入的参数(这里是document),剩余的构造参数会自动从DI容器中解析获取。- 这种方式完全复用了DI容器的注册配置,后续如果要替换
IObject1或IObject2的实现,只需修改DI注册代码即可,无需改动工厂逻辑。
内容的提问来源于stack exchange,提问作者Vastar
相关产品推荐
相关产品推荐

