如何避免重复传递对象至多个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
相关产品推荐
相关产品推荐

