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

如何避免重复传递对象至多个IServiceCollection扩展方法?

解决方案

方法1:先将MyObject注册为单例,扩展方法直接复用已注册实例

先把MyObject注册为全局单例,后续扩展方法无需传参,直接从服务集合中获取该实例:

public static class MyExtensions
{
    // 新增注册MyObject的扩展方法
    public static IServiceCollection AddMyObject(this IServiceCollection services, IMyObject myObject)
    {
        // 注册为单例,确保全局唯一实例
        services.AddSingleton<IMyObject>(myObject);
        return services;
    }

    public static IServiceCollection AddMyExtension1(this IServiceCollection services)
    {
        // 从服务集合中获取已注册的IMyObject实例
        var myObject = services.SingleOrDefault(sd => sd.ServiceType == typeof(IMyObject))?.ImplementationInstance as IMyObject;
        if (myObject == null)
        {
            throw new InvalidOperationException("请先调用AddMyObject注册IMyObject实例");
        }

        // 这里使用myObject执行注册逻辑
        // services.Add...
        return services;
    }

    public static IServiceCollection AddMyExtension2(this IServiceCollection services)
    {
        var myObject = services.SingleOrDefault(sd => sd.ServiceType == typeof(IMyObject))?.ImplementationInstance as IMyObject;
        if (myObject == null)
        {
            throw new InvalidOperationException("请先调用AddMyObject注册IMyObject实例");
        }

        // 业务逻辑实现
        return services;
    }
}

Program.cs中调用方式:

var myObject = new MyObject();
var builder = WebApplication.CreateBuilder(args);
builder.Services
       .AddMyObject(myObject)
       .AddMyExtension1()
       .AddMyExtension2()
       .AddMyExtension3()
       ...
       .AddMyExtensionN();

var app = builder.Build();
// ...
app.Run();

此方案只需传入一次myObject,既避免重复传参,也不会出现BuildServiceProvider导致的单例重复创建问题。

方法2:用自定义上下文类封装实例,实现链式调用

创建一个上下文类持有IMyObject和服务集合,所有扩展方法基于上下文实现,仅需初始化时传入一次实例:

// 自定义上下文类
public class MyServiceContext
{
    public IServiceCollection Services { get; }
    public IMyObject MyObject { get; }

    public MyServiceContext(IServiceCollection services, IMyObject myObject)
    {
        Services = services;
        MyObject = myObject;
    }
}

public static class MyExtensions
{
    // 初始化上下文的扩展方法
    public static MyServiceContext UseMyObject(this IServiceCollection services, IMyObject myObject)
    {
        // 可选:同时注册为单例,方便其他业务逻辑使用
        services.AddSingleton<IMyObject>(myObject);
        return new MyServiceContext(services, myObject);
    }

    // 基于上下文的扩展方法
    public static MyServiceContext AddMyExtension1(this MyServiceContext context)
    {
        var myObject = context.MyObject;
        var services = context.Services;

        // 执行依赖注册逻辑
        // services.Add...
        return context;
    }

    public static MyServiceContext AddMyExtension2(this MyServiceContext context)
    {
        var myObject = context.MyObject;
        var services = context.Services;

        // 业务逻辑实现
        return context;
    }

    // 可选:回到IServiceCollection的方法,兼容其他扩展调用
    public static IServiceCollection Build(this MyServiceContext context)
    {
        return context.Services;
    }
}

Program.cs中调用方式:

var myObject = new MyObject();
var builder = WebApplication.CreateBuilder(args);
builder.Services
       .UseMyObject(myObject)
       .AddMyExtension1()
       .AddMyExtension2()
       .AddMyExtension3()
       ...
       .AddMyExtensionN()
       .Build(); // 可选,如需继续链式调用其他IServiceCollection扩展

var app = builder.Build();
// ...
app.Run();

此方案通过上下文封装实例和服务集合,链式调用逻辑更连贯,代码可读性更强。

方法3:用主扩展方法统一传入实例,内部调用所有子扩展

如果不想修改现有扩展方法,可新增一个主扩展方法,传入myObject后内部自动调用所有需要的子扩展:

public static class MyExtensions
{
    // 主扩展方法,统一传入实例
    public static IServiceCollection AddAllMyExtensions(this IServiceCollection services, IMyObject myObject)
    {
        services.AddMyExtension1(myObject);
        services.AddMyExtension2(myObject);
        services.AddMyExtension3(myObject);
        // ... 调用其他子扩展方法
        services.AddMyExtensionN(myObject);
        return services;
    }

    // 保留原有的子扩展方法
    public static IServiceCollection AddMyExtension1(this IServiceCollection services, IMyObject myObject)
    {
        // 原有逻辑实现
        return services;
    }

    public static IServiceCollection AddMyExtension2(this IServiceCollection services, IMyObject myObject)
    {
        // 原有逻辑实现
        return services;
    }
}

Program.cs中调用方式:

var myObject = new MyObject();
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAllMyExtensions(myObject);

var app = builder.Build();
// ...
app.Run();

此方案改动最小,仅需新增一个整合方法,外部只需传一次实例即可完成所有扩展的注册。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 00:15:31