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

.NET Core 2.2依赖注入容器:对象构造后如何设置属性

解决.NET Core 2.2中服务构造后属性注入的循环依赖问题

这个场景我太熟悉了,循环依赖确实容易卡壳,尤其是没法通过构造函数注入的情况。咱们可以通过给IServiceCollection写一个扩展方法,来实现你想要的“构造完成后设置属性”的逻辑,具体方案如下:

1. 编写ServiceCollection扩展方法

首先创建一个扩展类,添加一个Inject方法,用来在服务实例化后执行属性注入的逻辑:

using Microsoft.Extensions.DependencyInjection;
using System;
using System.Linq;

public static class ServiceCollectionExtensions
{
    public static IServiceCollection Inject<TService>(this IServiceCollection services, Action<TService, IServiceProvider> configure)
        where TService : class
    {
        // 查找已注册的对应服务描述
        var descriptor = services.FirstOrDefault(d => d.ServiceType == typeof(TService));
        if (descriptor == null)
            throw new InvalidOperationException($"服务 {typeof(TService).Name} 未在容器中注册");

        // 根据原服务的生命周期,替换为工厂模式注册,实现构造后属性注入
        switch (descriptor.Lifetime)
        {
            case ServiceLifetime.Singleton:
                services.Replace(ServiceDescriptor.Singleton<TService>(sp =>
                {
                    var service = (TService)ActivatorUtilities.CreateInstance(sp, descriptor.ImplementationType);
                    configure(service, sp);
                    return service;
                }));
                break;
            case ServiceLifetime.Scoped:
                services.Replace(ServiceDescriptor.Scoped<TService>(sp =>
                {
                    var service = (TService)ActivatorUtilities.CreateInstance(sp, descriptor.ImplementationType);
                    configure(service, sp);
                    return service;
                }));
                break;
            case ServiceLifetime.Transient:
                services.Replace(ServiceDescriptor.Transient<TService>(sp =>
                {
                    var service = (TService)ActivatorUtilities.CreateInstance(sp, descriptor.ImplementationType);
                    configure(service, sp);
                    return service;
                }));
                break;
        }

        return services;
    }
}

2. 在你的服务注册中使用这个扩展

回到你的代码,注册完IServiceA和IServiceB之后,直接调用Inject方法来设置ServiceB的ServiceA属性:

services.AddSingleton<IServiceA, ServiceA>();
services.AddSingleton<IServiceB, ServiceB>();

// 用扩展方法实现构造后的属性注入
services.Inject<IServiceB>((serviceB, serviceProvider) => {
    serviceB.ServiceA = serviceProvider.GetService<IServiceA>();
});

为什么这个方案能解决循环依赖?

  • ServiceA的构造函数依赖IServiceB,在创建ServiceA时,IServiceB的实例已经被容器创建(因为都是Singleton生命周期);
  • ServiceB的ServiceA属性是在ServiceB实例化完成后才被设置的,不会触发新的实例创建,完美避开了构造函数层面的循环依赖。

注意事项

  • 如果你的服务是Scoped或Transient生命周期,上面的扩展方法也能适配,因为我们根据原服务的生命周期做了对应的处理;
  • 确保你注入的属性不会在服务的构造函数中被使用,否则可能会遇到空引用问题——毕竟属性是在构造完成后才设置的。

内容的提问来源于stack exchange,提问作者M T

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:19:29