.NET Core -核心组件
Hosting(服务托管主机)和管道(中间件)
托管服务注册实例
public class Sample01 { public class SystemClock : IHostedService { private Timer _timer; //启动服务 public Task StartAsync(CancellationToken cancellationToken) { _timer = new Timer(state => { Console.WriteLine($"Current Time:{DateTime.Now.ToLongTimeString()}"); }, null, 0, 1000); return Task.CompletedTask; } //服务停止 public Task StopAsync(CancellationToken cancellationToken) { _timer?.Dispose(); return Task.CompletedTask; } } public static void Start() { var host = new HostBuilder()//主机构建起 .ConfigureServices(collection => collection .AddSingleton<IHostedService, SystemClock>())//依赖注入 .Build(); host.Run();//运行主机 } }
托管服务注册示例 使用服务的方式注册(依赖注入)
public class Sample02 { /// <summary> /// 温度 /// </summary> public interface ITemperatureCollector { int Get(); } /// <summary> /// 湿度 /// </summary> public interface IHumidityCollector { int Get(); } /// <summary> /// 空气质量 /// </summary> public interface IAirQualityCollector { int Get(); } public class Collector: ITemperatureCollector, IHumidityCollector, IAirQualityCollector { int ITemperatureCollector.Get() { var random = new Random(); return random.Next(0, 100); } int IHumidityCollector.Get() { var random = new Random(); return random.Next(0, 100); } int IAirQualityCollector.Get() { var random = new Random(); return random.Next(0, 100); } } public class AirEnvironmentService : IHostedService { private readonly ITemperatureCollector _temperatureCollector; private readonly IHumidityCollector _humidityCollector; private readonly IAirQualityCollector _airQualityCollector; private Timer _timer; public AirEnvironmentService( ITemperatureCollector temperatureCollector, IHumidityCollector humidityCollector, IAirQualityCollector airQualityCollector ) { _temperatureCollector = temperatureCollector; _humidityCollector = humidityCollector; _airQualityCollector = airQualityCollector; } public Task StartAsync(CancellationToken cancellationToken) { _timer = new Timer(state => { Console.WriteLine($"温度:{_temperatureCollector.Get(), -10}" + $"湿度:{_humidityCollector.Get(), -10}" + $"空气质量:{_airQualityCollector.Get(), -10}" + $"时间:{DateTime.Now.ToLongTimeString()}"); }, null,0, 1000); return Task.CompletedTask; } public Task StopAsync(CancellationToken cancellationToken) { _timer?.Dispose(); return Task.CompletedTask; } } public static void Start() { var collector = new Collector(); var host = new HostBuilder() .ConfigureServices(collection => collection .AddSingleton<ITemperatureCollector>(collector) .AddSingleton<IHumidityCollector>(collector) .AddSingleton<IAirQualityCollector>(collector) .AddHostedService<AirEnvironmentService>()//环境服务 ).Build(); host.Run(); } }
托管服务注册示例 使用服务的方式注册同时使用选项服务获取配置文件设置服务内的时间
public class Sample03 { /// <summary> /// 温度 /// </summary> public interface ITemperatureCollector { int Get(); } /// <summary> /// 湿度 /// </summary> public interface IHumidityCollector { int Get(); } /// <summary> /// 空气质量 /// </summary> public interface IAirQualityCollector { int Get(); } public class Collector: ITemperatureCollector, IHumidityCollector, IAirQualityCollector { int ITemperatureCollector.Get() { var random = new Random(); return random.Next(0, 100); } int IHumidityCollector.Get() { var random = new Random(); return random.Next(0, 100); } int IAirQualityCollector.Get() { var random = new Random(); return random.Next(0, 100); } } //选项类 public class AirEnvironmentOptions { public long Interval { get; set; } } public class AirEnvironmentService : IHostedService { private readonly ITemperatureCollector _temperatureCollector; private readonly IHumidityCollector _humidityCollector; private readonly IAirQualityCollector _airQualityCollector; private readonly AirEnvironmentOptions _options; private Timer _timer; public AirEnvironmentService( ITemperatureCollector temperatureCollector, IHumidityCollector humidityCollector, IAirQualityCollector airQualityCollector, IOptions<AirEnvironmentOptions> options ) { _temperatureCollector = temperatureCollector; _humidityCollector = humidityCollector; _airQualityCollector = airQualityCollector; _options = options.Value; } public Task StartAsync(CancellationToken cancellationToken) { _timer = new Timer(state => { Console.WriteLine($"温度:{_temperatureCollector.Get(), -10}" + $"湿度:{_humidityCollector.Get(), -10}" + $"空气质量:{_airQualityCollector.Get(), -10}" + $"时间:{DateTime.Now.ToLongTimeString()}"); }, null,0, _options.Interval); return Task.CompletedTask; } public Task StopAsync(CancellationToken cancellationToken) { _timer?.Dispose(); return Task.CompletedTask; } } public static void Start(string[] args) { var collector = new Collector(); var host = new HostBuilder() //通过命令行指定的方式获取对应的配置文件 .ConfigureHostConfiguration(builder => builder.AddCommandLine(args)) //用于配置托管服务的配置对象利用委托注册配置文件 .ConfigureAppConfiguration((context, builder) => builder .AddJsonFile("appsettings.json", false) //添加环境名称 .AddJsonFile($"appsettings.{context.HostingEnvironment.EnvironmentName}.json",true) ) //这里有两个参数的context这个是主机上下文对象 .ConfigureServices((context, collection) => collection .AddSingleton<ITemperatureCollector>(collector) .AddSingleton<IHumidityCollector>(collector) .AddSingleton<IAirQualityCollector>(collector) .AddHostedService<AirEnvironmentService>() .AddOptions() .Configure<AirEnvironmentOptions>( context.Configuration.GetSection("AirEnvironment"))//获取配置文件中的配置 ).Build(); host.Run(); } }
加入日志:
public class Sample04 { /// <summary> /// 温度 /// </summary> public interface ITemperatureCollector { int Get(); } /// <summary> /// 湿度 /// </summary> public interface IHumidityCollector { int Get(); } /// <summary> /// 空气质量 /// </summary> public interface IAirQualityCollector { int Get(); } public class Collector: ITemperatureCollector, IHumidityCollector, IAirQualityCollector { int ITemperatureCollector.Get() { var random = new Random(); return random.Next(0, 100); } int IHumidityCollector.Get() { var random = new Random(); return random.Next(0, 100); } int IAirQualityCollector.Get() { var random = new Random(); return random.Next(0, 100); } } public class AirEnvironmentOptions { public long Interval { get; set; } } /// <summary> /// 控制质量发布器 /// </summary> public class AirEnvironmentPublisher { private const string Template = "温度:{temperature, -10}" + "湿度:{humidity, -10}" + "空气质量:{airQuality, -10}" + "时间:{now}"; private readonly Action<ILogger, int,int,int,string, Exception> _logAction; private readonly ILogger _logger; /// <summary> /// 控制质量发布器 /// </summary> /// <param name="logger"></param> public AirEnvironmentPublisher(ILogger<AirEnvironmentPublisher> logger) { _logger = logger; _logAction = LoggerMessage.Define<int, int, int, string>(LogLevel.Information, 0, Template); } public void Publish(int temp, int humi, int airq) { _logAction(_logger, temp, humi, airq, DateTime.Now.ToLongTimeString(), null); } } public class AirEnvironmentService : IHostedService { private readonly ITemperatureCollector _temperatureCollector; private readonly IHumidityCollector _humidityCollector; private readonly IAirQualityCollector _airQualityCollector; private readonly AirEnvironmentPublisher _publisher; private readonly AirEnvironmentOptions _options; private Timer _timer; public AirEnvironmentService( ITemperatureCollector temperatureCollector, IHumidityCollector humidityCollector, IAirQualityCollector airQualityCollector, AirEnvironmentPublisher publisher, IOptions<AirEnvironmentOptions> options ) { _temperatureCollector = temperatureCollector; _humidityCollector = humidityCollector; _airQualityCollector = airQualityCollector; _publisher = publisher; _options = options.Value; } public Task StartAsync(CancellationToken cancellationToken) { _timer = new Timer(state => { _publisher.Publish( _temperatureCollector.Get(), _humidityCollector.Get(), _airQualityCollector.Get()); }, null,0, _options.Interval); return Task.CompletedTask; } public Task StopAsync(CancellationToken cancellationToken) { _timer?.Dispose(); return Task.CompletedTask; } } public static void Start() { var collector = new Collector(); var host = new HostBuilder() .ConfigureAppConfiguration((context,builder) => builder.AddJsonFile("appsettings.json")) .ConfigureServices((context, collection) => collection .AddSingleton<ITemperatureCollector>(collector) .AddSingleton<IHumidityCollector>(collector) .AddSingleton<IAirQualityCollector>(collector) .AddSingleton<AirEnvironmentPublisher>() .AddHostedService<AirEnvironmentService>() .AddOptions() .Configure<AirEnvironmentOptions>( context.Configuration.GetSection("AirEnvironment")) ) .ConfigureLogging((context, builder) => builder .AddConfiguration(context.Configuration.GetSection("Logging")) .AddConsole()) .Build(); host.Run(); } }
web开发平台 请求处理管道
路由,会话,缓存,认证
长时间运行的后台服务,是一个托管服务,
public static class Sample01 { public static void Start() { var host = Host.CreateDefaultBuilder() //这里没有用CreateDefaultBuilder,这个是因为CreateDefaultBuilder创建其他默认额外的一些东西或者配置,例如Kestral .ConfigureWebHost(builder => builder //使用kestrel .UseKestrel()
//这个方法是用来注册中间件的 .Configure(app => app.Run(context => context.Response.WriteAsync("Hello!")) ) ).Build(); host.Run(); } }
管道和中间件的关系 如图:
中间件代码上的体现是一个委托 Func<RequestDelegate,RequestDelegate> Http请求处理器
中间件的注册可以用 上面的方法(中间件委托的方式定义中间件);
public static class Sample02 { public static void Start() { var host = Host.CreateDefaultBuilder() .ConfigureWebHostDefaults(builder => builder .Configure(app => app //用use方法加入中间件 .Use(Middleware1) .Use(Middleware2) ) ).Build(); host.Run(); } /// <summary> /// 使用原始的委托对象定义中间件 /// </summary> /// <param name="next"></param> /// <returns></returns> private static RequestDelegate Middleware1(RequestDelegate next) { async Task App(HttpContext context) { await context.Response.WriteAsync("Middleware 1 Begin."); await next(context); await context.Response.WriteAsync("Middleware 1 End."); } return App; } private static RequestDelegate Middleware2(RequestDelegate next) { async Task App(HttpContext context) { await context.Response.WriteAsync("Middleware 2 Begin."); } return App; } }
同时中间件还有其他方法 (强类型定义:实现IMiddleWare接口 )
public class Sample03 { public class HelloMiddleware : IMiddleware { /// <summary> /// /// </summary> /// <param name="context">当前请求的上下文对象</param> /// <param name="next">下一个中间件的管道委托</param> /// <returns></returns> public async Task InvokeAsync(HttpContext context, RequestDelegate next) { await context.Response.WriteAsync("Hello"); } } public static void Start() { var host = Host.CreateDefaultBuilder() .ConfigureWebHostDefaults(builder => builder //中间件的注册 .ConfigureServices(collection => collection.AddSingleton<HelloMiddleware>()) .Configure(app => app .UseMiddleware<HelloMiddleware>() ) ).Build(); host.Run(); } }
同时中间件还有其他方法 (基于约定:不需要实现任何接口 )
需要一个有效的公共构造函数,而且包含http处理器类型(参数),还需要有 InvokeAsync 这个方法
public class Sample04 { /// <summary> /// 通过约定的方式定义中间件 /// </summary> public class HelloMiddleware { private readonly RequestDelegate _next; private readonly string _content; private readonly bool _isToNext; public HelloMiddleware(RequestDelegate next, string content, bool isToNext = false) { _next = next; _content = content; _isToNext = isToNext; } /// <summary> /// 必须要有的方法 /// </summary> /// <param name="httpContext"></param> /// <returns></returns> public async Task InvokeAsync(HttpContext httpContext) { await httpContext.Response.WriteAsync($"Hello {_content}!\r\n"); if (_isToNext) await _next(httpContext); } } public static void Start() { var host = Host.CreateDefaultBuilder() .ConfigureWebHostDefaults(builder => builder //中间件的注册,与强类型不一致这里不需要服务,直接可以配置中间件,框架会自动注册为单例的模式的服务 .Configure(app => app .UseMiddleware<HelloMiddleware>("Rick", true) .UseMiddleware<HelloMiddleware>("Motry") ) ).Build(); host.Run(); } }
如何在asp.net core 中进行服务注册,和中间件配置 演示
public class Sample05 { /// <summary> /// 定义Startup类型 这个是Asp.net 中约定的启动类 /// </summary> public class Startup { /// <summary> /// 服务的注册 This method gets called by the runtime. Use this method to add services to the container. /// </summary> /// <param name="services"></param> public void ConfigureServices(IServiceCollection services) { //服务注册是可以没有的 } /// <summary> /// 中间件的注册 This method gets called by the runtime. Use this method to configure the HTTP request pipeline /// </summary> /// <param name="app"></param> public void Configure(IApplicationBuilder app) { //但是中间件一般都会有一个以上 } } public void Strat() { var host = Host.CreateDefaultBuilder() .ConfigureWebHostDefaults(builder => builder .UseStartup<Startup>()) .Build(); host.Run(); } }
public static class Sample06 { public class Startup { public void ConfigureServices(IServiceCollection services) { //答应出asp.net core 预先已经注册的服务 foreach (var service in services) { var serviceName = service.ServiceType.Name; var implType = service.ImplementationType; if (implType != null) { Console.WriteLine($"{service.Lifetime, -15}{serviceName,-40}{implType.Name}"); } } } public void Configure(IApplicationBuilder app) { } } public static void Start() { var host = Host.CreateDefaultBuilder() .ConfigureWebHostDefaults(builder => builder .UseStartup<Startup>()) .Build(); host.Run(); } }
使用Startup构造函数注入方式例子
public class Sample07 { public class Startup { /// <summary> /// 构造函数 注入 /// </summary> /// <param name="configuration">配置对象</param> /// <param name="hostingEnvironment">主机环境对象</param> public Startup(IConfiguration configuration, IHostEnvironment hostingEnvironment) { Debug.Assert(configuration != null); Debug.Assert(hostingEnvironment != null); } public void ConfigureServices(IServiceCollection services) { } public void Configure(IApplicationBuilder app) { } } public static void Start() { var host = Host.CreateDefaultBuilder() .ConfigureWebHostDefaults(builder => builder .UseStartup<Startup>()) .Build(); host.Run(); } }
演示注入服务的注意问题:
public class Sample08 { public class Test1{ }; public class Test2{ }; public class Startup { // public Startup(Test1 test1) // { // 这里会报错 ,因为Startup 构造函数注入是有限制的,所以这里只能用于注册框架提供的公共服务 也就是 上面例子打印出来的服务 // } public void ConfigureServices(IServiceCollection services) { services.AddSingleton<Test2>();//这里注册一个服务 } /// <summary> /// 这个比比较晚任何的服务都可以被注入进来,中间件也可以被注入服务 /// </summary> /// <param name="app"></param> /// <param name="test1"></param> /// <param name="test2"></param> public void Configure(IApplicationBuilder app, Test1 test1, Test2 test2) { Debug.Assert(test1 != null); Debug.Assert(test2 != null); } } public static void Start() { var host = Host.CreateDefaultBuilder() //这里也注册一个服务 .ConfigureServices(collection => collection.AddSingleton<Test1>()) .ConfigureWebHostDefaults(builder => builder .UseStartup<Startup>()) .Build(); host.Run(); } }
演示中间件中也可以注入服务;不仅支持构造函数注入,还支持特定方法InvokeAsync进行注入。但是要注意的是中间件中的构造函数注入和特定方式注入有一个本质的区别
由于中间件的默认生命周期为单例模式,所以我们不应该在它的构造函数中注入为生命周期scope的服务,所以scope比较适合通过特定方法注入!
public class Sample09 { public class Test1{ }; public class Test2{ }; public class TestMiddleware { private readonly RequestDelegate _next;
// 构造函数注入
public TestMiddleware(RequestDelegate next, Test1 test1, Test2 test2) { Debug.Assert(test1 != null); Debug.Assert(test2 != null); _next = next; } public async Task InvokeAsync(HttpContext httpContext) { Debug.Assert(_next != null); await httpContext.Response.WriteAsync("Test"); } } public class Startup { public void ConfigureServices(IServiceCollection services) { services .AddSingleton<Test1>() .AddSingleton<Test2>(); } public void Configure(IApplicationBuilder app) { app.UseMiddleware<TestMiddleware>(); } } public static void Start() { var host = Host.CreateDefaultBuilder() .ConfigureWebHostDefaults(builder => builder .UseStartup<Startup>()) .Build(); host.Run(); } }
public class Sample10 { public class Test1{ }; public class Test2{ }; public class TestMiddleware { private readonly RequestDelegate _next; /// <summary> /// 构造函数 /// </summary> /// <param name="next"></param> public TestMiddleware(RequestDelegate next) { _next = next; } /// <summary> /// 特定方法注入 /// </summary> /// <param name="httpContext"></param> /// <param name="test1"></param> /// <param name="test2"></param> /// <returns></returns> public async Task ,(HttpContext httpContext,Test1 test1, Test2 test2) { Debug.Assert(test1 != null); Debug.Assert(test2 != null); await httpContext.Response.WriteAsync("Test"); } } public class Startup { public void ConfigureServices(IServiceCollection services) { services .AddSingleton<Test1>() .AddSingleton<Test2>(); } public void Configure(IApplicationBuilder app) { app.UseMiddleware<TestMiddleware>(); } } public static void Start() { var host = Host.CreateDefaultBuilder() .ConfigureWebHostDefaults(builder => builder .UseStartup<Startup>()) .Build(); host.Run(); } }
在MVc中的应用主要式在两个地方注入服务的:
在控制器类型中注入和在示图中
namespace ConsoleApp2 { public class Sample11 { public class Test1{ } public class Test2{ } public static void Start() { var host = Host.CreateDefaultBuilder() .ConfigureWebHostDefaults(builder => builder .ConfigureServices(collection => collection .AddSingleton<Test1>() .AddSingleton<Test2>() .AddControllersWithViews()) .Configure(app=>app .UseRouting() .UseEndpoints(routeBuilder => routeBuilder.MapControllers())) ) .Build(); host.Run(); } } public class Startup { public void Configure(IApplicationBuilder app) { } public void ConfigureServices(IServiceCollection services) { } } public class HomeController : Controller { private readonly Sample11.Test1 _test1; public HomeController(Sample11.Test1 test1) { _test1 = test1; } [HttpGet("/")] public IActionResult Index() { ViewBag.Test1 = _test1; return View(); } } }
试图注入
@using ConsoleApp2 @inject Sample11.Test2 Test2 Foo: @ViewBag.Test1.GetType().AssemblyQualifiedName <br /> Bar: @Test2.GetType().AssemblyQualifiedName
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)