C#怎么使用ActivatorUtilities .NET DI容器高级用法

来源:AI视频音频作者:缓存小熊猫头衔:程序员
导读:本期聚焦于小伙伴创作的《C#怎么使用ActivatorUtilities .NET DI容器高级用法》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C#怎么使用ActivatorUtilities .NET DI容器高级用法》有用,将其分享出去将是对创作者最好的鼓励。

在.NET的依赖注入体系中,基础的IServiceProvider只能解析容器中已注册的服务类型,如果某个类型的构造函数包含未在容器中注册的参数,直接使用GetService方法会返回null或者抛出异常。ActivatorUtilities类提供了补充能力,能够利用容器中已注册的服务,自动填充构造函数的已注册参数,未注册的参数则由开发者手动传入,从而实现复杂对象的动态创建。

C#怎么使用ActivatorUtilities .NET DI容器高级用法

ActivatorUtilities核心方法介绍

ActivatorUtilities主要包含两个常用的静态方法,分别适用于不同的创建场景:

  • CreateInstance:用于创建指定类型的实例,构造函数的参数中,已在容器中注册的类型会自动从容器解析,未注册的参数需要开发者按顺序传入。
  • GetServiceOrCreateInstance:尝试从容器中获取指定类型的实例,如果容器中未注册该类型,则自动使用ActivatorUtilities创建实例,同样支持混合构造参数。

基础使用示例

首先我们定义几个基础的服务类型,模拟实际的业务场景:

// 已在容器中注册的服务
public interface ILogService
{
    void Log(string message);
}

public class ConsoleLogService : ILogService
{
    public void Log(string message)
    {
        Console.WriteLine($"日志内容:{message}");
    }
}

// 需要创建实例的目标类型,构造函数包含已注册和未注册的参数
public class UserService
{
    private readonly ILogService _logService;
    private readonly string _userName;
    private readonly int _userAge;

    // ILogService已在容器中注册,string和int未在容器中注册
    public UserService(ILogService logService, string userName, int userAge)
    {
        _logService = logService;
        _userName = userName;
        _userAge = userAge;
    }

    public void ShowUserInfo()
    {
        _logService.Log($"用户姓名:{_userName},年龄:{_userAge}");
    }
}

接下来配置DI容器,注册ILogService服务,然后使用ActivatorUtilities创建UserService实例:

using Microsoft.Extensions.DependencyInjection;
using System;

class Program
{
    static void Main()
    {
        // 创建DI容器并注册服务
        IServiceCollection services = new ServiceCollection();
        services.AddTransient<ILogService, ConsoleLogService>();
        IServiceProvider serviceProvider = services.BuildServiceProvider();

        // 使用ActivatorUtilities.CreateInstance创建实例
        // 第一个参数是IServiceProvider,第二个参数是目标类型,后续参数是未注册的构造参数,按顺序传入
        UserService userService = ActivatorUtilities.CreateInstance<UserService>(serviceProvider, "张三", 25);
        userService.ShowUserInfo();

        // 使用GetServiceOrCreateInstance方法,如果未注册UserService则自动创建
        // 注意该方法要求目标类型的构造函数参数要么全在容器中注册,要么未注册的参数有默认值
        // 此处UserService有未注册参数,所以需要确保参数可自动填充,或者改用CreateInstance
        // 下面演示无未注册参数的类型使用GetServiceOrCreateInstance
        public class SimpleService
        {
            private readonly ILogService _logService;
            public SimpleService(ILogService logService)
            {
                _logService = logService;
            }
            public void DoWork()
            {
                _logService.Log("执行简单任务");
            }
        }
        SimpleService simpleService = ActivatorUtilities.GetServiceOrCreateInstance<SimpleService>(serviceProvider);
        simpleService.DoWork();
    }
}

实际应用场景

动态创建带运行时参数的服务实例

当某个服务的构造参数需要运行时才能确定数值,比如用户ID、配置路径等,这些参数不适合提前注册到DI容器中,此时可以使用ActivatorUtilities混合容器服务和运行时参数创建实例。

public class OrderService
{
    private readonly ILogService _logService;
    private readonly string _orderId;

    public OrderService(ILogService logService, string orderId)
    {
        _logService = logService;
        _orderId = orderId;
    }

    public void ProcessOrder()
    {
        _logService.Log($"处理订单,订单ID:{_orderId}");
    }
}

// 运行时获取订单ID后创建实例
string currentOrderId = "ORD202405001";
OrderService orderService = ActivatorUtilities.CreateInstance<OrderService>(serviceProvider, currentOrderId);
orderService.ProcessOrder();

工厂模式中结合DI容器

在工厂模式中,工厂类需要创建多种不同类型的实例,这些实例的构造函数可能包含部分公共的已注册服务,使用ActivatorUtilities可以避免手动从容器中解析每个依赖,简化工厂的实现逻辑。

public interface IFactory
{
    T Create<T>(params object[] args) where T : class;
}

public class ServiceFactory : IFactory
{
    private readonly IServiceProvider _serviceProvider;

    public ServiceFactory(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public T Create<T>(params object[] args) where T : class
    {
        return ActivatorUtilities.CreateInstance<T>(_serviceProvider, args);
    }
}

// 使用工厂创建实例
IFactory factory = new ServiceFactory(serviceProvider);
UserService user = factory.Create<UserService>("李四", 30);
user.ShowUserInfo();

注意事项

  • ActivatorUtilities只能解析公共的构造函数,如果目标类型只有私有构造函数,创建实例会失败。
  • 如果目标类型有多个公共构造函数,ActivatorUtilities会选择参数最多的那个公共构造函数,如果多个构造函数参数数量相同,可能会抛出异常,建议目标类型只保留一个公共构造函数。
  • 传入的未注册参数顺序需要和构造函数中未注册参数的声明顺序一致,否则会导致参数赋值错误。
  • ActivatorUtilities创建实例时不会自动跟踪实例的生命周期,生命周期管理需要开发者自行处理,或者结合容器的生命周期配置使用。

总结

ActivatorUtilities是.NET DI容器的重要补充,解决了基础DI无法处理混合构造参数的对象创建问题,在动态实例创建、工厂模式、运行时参数注入等场景中非常实用。开发者只需要掌握CreateInstanceGetServiceOrCreateInstance两个方法的使用方式,就能应对大部分高级DI使用需求,让依赖注入的使用更加灵活高效。

ActivatorUtilitiesC#DI容器依赖注入修改时间:2026-06-19 10:45:27

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。