如何配置.NET Core控制台应用DI 无需每次调用GetService获取实例
自动注入的本质
ASP.NET 中不需要手动调用GetService,是因为框架本身接管了控制器、中间件等入口类型的实例化流程:框架会自动从DI容器中解析这些类型构造函数的所有参数,完成依赖注入后再返回实例。控制台应用默认没有内置这套入口类型的自动解析逻辑,只需要简单配置就能实现完全一致的使用体验。
推荐实现:使用.NET通用主机
官方提供的Microsoft.Extensions.Hosting包已经封装了完整的DI自动解析能力,同时还兼容ASP.NET生态的配置、日志、后台任务等组件,是控制台应用的首选方案:
- 首先安装
Microsoft.Extensions.HostingNuGet包 - 按如下结构编写代码:
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; // 构建主机,注册服务 var host = Host.CreateDefaultBuilder(args) .ConfigureServices(services => { // 注册业务服务 services.AddScoped<IBusiness, Business>(); services.AddScoped<IBoardGameRepository, BoardGameRepository>(); // 注册应用入口执行类,等价于ASP.NET中框架自动注册控制器 services.AddTransient<App>(); }) .Build(); // 全局仅需要手动调用这一次解析入口类 var app = host.Services.GetRequiredService<App>(); // 执行业务逻辑 app.Run(); // 所有业务逻辑都可以放到入口类中,依赖直接通过构造函数注入 public class App { private readonly IBusiness _business; private readonly IBoardGameRepository _boardGameRepository; // 所有注册过的服务都可以在这里自动注入,不需要手动传参 public App(IBusiness business, IBoardGameRepository boardGameRepository) { _business = business; _boardGameRepository = boardGameRepository; } public void Run() { _business.DoSomeBusiness(); var games = _boardGameRepository.GetAllBoardGames(); // 后续其他业务逻辑里的依赖也会自动递归解析,无需再调用GetService } } // 以下是示例服务定义 public interface IBusiness { void DoSomeBusiness(); } public class Business : IBusiness { public void DoSomeBusiness() { Console.Write("This is very serious business stuff"); } } public interface IBoardGameRepository { List<string> GetAllBoardGames(); } public class BoardGameRepository : IBoardGameRepository { public List<string> GetAllBoardGames() { return new List<string> { "Catan", "Gloomhaven", "Ticket to Ride" }; } }
额外说明
如果需要使用Scoped生命周期的服务,和ASP.NET中的用法完全一致,你可以通过注入IServiceScopeFactory来手动创建作用域,容器会自动解析作用域内的所有服务依赖。
内容的提问来源于stack exchange,提问作者Dmitriy Grinevich
相关产品推荐
相关产品推荐

