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

并行for循环中向容器提供运行时数据的DI实现合理性探讨

问题与代码示例

业务层代码

public class Factor1(int FactorX, int FactorY) : IFactors;
public class Factor2(int FactorX, int FactorY, int FZ) : IFactors;

public interface IFactors
{
    int FactorX { get; set; }
    int FactorY { get; set; }
}

public class BusinessLayerClass1
{
    IFactors _factorObj;
    public BusinessLayerClass1(IFactors factorObj)
    {
        _factorObj = factorObj;
    }
    public void Call() =>
        new BusinessLayerClass2(_factorObj).ShowFactors();
}

public class BusinessLayerClass2
{
    IFactors _factorObj;
    public BusinessLayerClass2(IFactors factorObj)
    {
        _factorObj = factorObj;
    }

    public void ShowFactors()
    {
        Debug.WriteLine(String.Concat(_factorObj.FactorX.ToString(), " - " +
         _factorObj.FactorY.ToString()));
    }
}

主程序代码

using SimpleInjector;

class Program
{
    public static void Main(string[] args)
    {
        List<Task> tasks = new List<Task>();
        for (var i = 0; i < 10; i++)
        {
            tasks.Add(Task.Factory.StartNew((num) =>
            {
                int num_ = (int)num;
                var factorObj = new Factor1() { FactorX = num_, FactorY = num_ + 1 };
                var container = new Container();
                var lifestyle = Lifestyle.Transient;
                container.Register<BusinessLayerClass1>(lifestyle);
                container.Register<BusinessLayerClass2>(lifestyle);
                container.RegisterInstance<IFactors>(factorObj);
                container.Verify();
                var BL = container.GetInstance<BusinessLayerClass1>();
                BL.Call();
            }, i));
        }
        Task.WaitAll(tasks.ToArray());
    }
}

疑问

当前代码可运行,但存在以下疑问:

  • 该DI实现方式是否正确?
  • 若正确,是否有更便捷的优化方案?
  • 若不正确,针对此场景应如何正确实现DI?

回答

一、当前实现的问题

你的DI实现不符合最佳实践,存在明显问题:

  1. 容器重复创建:每个Task里都实例化新的Container,DI容器的核心价值是作为全局服务容器复用,重复创建会完全丧失DI的优势,还带来不必要的性能开销。
  2. 手动实例化依赖:BusinessLayerClass1.Call()里直接new BusinessLayerClass2(_factorObj),违背了DI的核心原则——依赖应通过容器注入而非手动创建,导致类之间耦合度高,无法利用容器的生命周期管理能力。
  3. IFactors注册语义错误:RegisterInstance用于注册单例实例,但这里每个Task的Factor1是独立的,用该方法虽然能运行,但语义完全错误,应该用工厂方式处理动态实例的创建。

二、正确的优化实现方案

针对你的场景(Factor1需异步创建,业务类依赖IFactors),优化步骤如下:

1. 重构业务层,消除手动实例化

修改BusinessLayerClass1,让BusinessLayerClass2通过构造函数注入,彻底交给容器管理依赖:

public class BusinessLayerClass1
{
    private readonly BusinessLayerClass2 _businessLayerClass2;

    // 直接注入BusinessLayerClass2,而非IFactors
    public BusinessLayerClass1(BusinessLayerClass2 businessLayerClass2)
    {
        _businessLayerClass2 = businessLayerClass2;
    }

    public void Call() => _businessLayerClass2.ShowFactors();
}

2. 全局初始化容器,复用实例

DI容器应在程序启动时初始化一次,而非每个Task重复创建。针对每个Task的动态Factor1实例,利用SimpleInjector的GetInstance重载传入自定义依赖:

优化后的主程序代码

using SimpleInjector;

class Program
{
    public static void Main(string[] args)
    {
        // 全局初始化一次容器
        var container = new Container();
        // 注册业务类为Transient(每次获取都创建新实例)
        container.Register<BusinessLayerClass1>(Lifestyle.Transient);
        container.Register<BusinessLayerClass2>(Lifestyle.Transient);
        container.Verify();

        List<Task> tasks = new List<Task>();
        for (var i = 0; i < 10; i++)
        {
            int num = i; // 捕获循环变量,避免闭包问题
            tasks.Add(Task.Run(() =>
            {
                // 异步创建Factor1实例
                var factorObj = new Factor1(num, num + 1);
                
                // 传入自定义的IFactors实例,获取业务类对象
                var bl1 = container.GetInstance<BusinessLayerClass1>(new[] { factorObj });
                bl1.Call();
            }));
        }
        Task.WaitAll(tasks.ToArray());
    }
}

注:用Task.Run替代Task.Factory.StartNew,是因为Task.Run更适合异步操作,能避免StartNew的一些潜在问题。

3. 进阶优化:用工厂封装Factor1的创建

如果Factor1的创建逻辑复杂,可封装成工厂类,让业务类通过工厂按需创建实例:

public interface IFactorFactory
{
    IFactors CreateFactor1(int x, int y);
}

public class FactorFactory : IFactorFactory
{
    public IFactors CreateFactor1(int x, int y) => new Factor1(x, y);
}

然后在容器中注册工厂:

container.Register<IFactorFactory, FactorFactory>(Lifestyle.Singleton);

业务类注入工厂后,可灵活创建IFactors实例,更符合单一职责原则。

三、总结

当前的DI实现不正确,核心问题是容器重复创建、手动实例化依赖、注册方式语义错误。优化后通过全局复用容器、消除手动实例化、正确处理动态依赖的方式,既符合DI最佳实践,又满足Factor1异步创建的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 10:05:21