如何在Microsoft.Extensions.DependencyInjection中实现Autofac的Lambda注册等效功能?
在ASP.NET Core内置DI中实现Autofac风格的Lambda注册
你尝试的代码无法编译,原因是AddScoped<TService, TImplementation>的泛型参数要求传入具体类型,而非方法调用。ASP.NET Core内置DI提供了接受工厂委托的重载方法,用来实现和Autofac中Register(c => ...)一致的逻辑。
正确实现方式
根据你的场景,有两种常见写法:
1. 无需从DI容器获取其他依赖的情况
直接使用接受Func<IServiceProvider, TService>的AddScoped重载,在委托中调用你的GetCommandContext方法:
services.AddScoped<IAppQuerier, AppQuerier>(); // 标准注册 // 正确写法:使用工厂委托 services.AddScoped<IAppDbContext>(_ => GetCommandContext()); private IAppDbContext GetCommandContext() { // 注意:确保Substitute的类型和返回值匹配(这里应该是IAppDbContext而非ICommandsContext) var appDbContext = Substitute.For<IAppDbContext>(); var roundOccurrences = AppTestsData.GetRoundOccurrences(); appDbContext.RoundOccurrences.Returns(roundOccurrences); return appDbContext; }
2. 需要从DI容器获取其他服务的情况
如果你的GetCommandContext需要依赖DI中的其他服务,可以修改方法接受IServiceProvider参数,在委托中传入容器实例:
services.AddScoped<IAppQuerier, AppQuerier>(); // 传入IServiceProvider给工厂方法 services.AddScoped<IAppDbContext>(sp => GetCommandContext(sp)); private IAppDbContext GetCommandContext(IServiceProvider sp) { // 从DI容器获取所需依赖 var someDependency = sp.GetRequiredService<ISomeDependency>(); var appDbContext = Substitute.For<IAppDbContext>(); var roundOccurrences = AppTestsData.GetRoundOccurrences(); appDbContext.RoundOccurrences.Returns(roundOccurrences); return appDbContext; }
注意事项
- 确保
GetCommandContext返回的实例类型和IAppDbContext兼容(你原代码中Substitute.For<ICommandsContext>()返回的是ICommandsContext,如果它未实现IAppDbContext,会导致类型转换错误,需修正为Substitute.For<IAppDbContext>())。 - 委托中的
IServiceProvider参数可以用来获取DI容器中注册的其他服务,这和Autofac注册时的c(IComponentContext)作用类似。
内容的提问来源于stack exchange,提问作者Mateusz Kaleta
相关产品推荐
相关产品推荐

