You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 17:10:42