ASP.NET Core框架中 依赖注入 LINQ语句 配置系统 日志
异步
委托
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 namespace ConsoleApp1 ;class MainClass { public static void Main (string [] args ) { Action a1 = F1; a1(); Action<int > a_int = F_int; a_int(520 ); } static void F1 () { Console.WriteLine("hello world!" ); } static void F_int (int a ) { Console.WriteLine(a); } } Func<int > F1 = function; F1(); int function () { return 520 ; }
Lambda 表达式
1 2 3 4 5 6 7 8 9 namespace ConsoleApp1 ;class MainClass { public static void Main (string [] args ) { Action<int , int > a1 = (int i, int j) => { Console.WriteLine("hello world!" ); }; a1(1 , 2 ); } }
yeild
yield关键字用于简化实现迭代器的方法。迭代器是一种特殊的方法,它可以逐步返回 集合中的元素,而不是一次性返回整个集合。使用yield可以让方法在每次调用时返回一个元素,并在需要时保持其当前状态,以便下次调用时继续执行。
LINQ
几乎里面的所有的扩展方法都是针对 IEnumerable接口的
所有能返回集合的都是返回IEnumerable
处于System.Linq命名空间中
常用方法
Where() 筛选出符合条件的数据
Single() 有且只有一条数据时返回
SingleOrDefault()
First():至少有一条时返回第一条
FirstOrDefault()
Order() 正序排序
OrderByDescending() 倒序排序
OrderBy() 按照自定义要求排序
ThenBy()
Skip() Take()
聚合函数
分组函数
返回值IEnumerable<IGrouping<T,Y>>
投影
按照某种规则将一组数据映射为另一组数据
集合转换
控制反转
1.服务定位器(ServiceLocator)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 using Microsoft.Extensions.DependencyInjection;namespace ConsoleApp1 ;class MainClass { public interface ITestService { public string ? Name { get ; set ; } public void SayHi () ; } public class TestServiceImpl : ITestService { public string ? Name { get ; set ; } public void SayHi () { Console.WriteLine($"Hi!My name is {Name} " ); } } public static void Main (string [] args ) { ServiceCollection services = new ServiceCollection(); services.AddTransient<TestServiceImpl>(); using (ServiceProvider sp = services.BuildServiceProvider()) { TestServiceImpl t = sp.GetService<TestServiceImpl>(); t.Name = "WangMC" ; t.SayHi(); } } }
2.依赖注入(Dependency Injection)
.NET控制反转组件取名为DependencyInjection,但其中包含服务定位器
使用前要安装Microsoft.Extensions.DependencyInjection
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 using Microsoft.Extensions.DependencyInjection;namespace ConsoleApp1 ;class MainClass { public static void Main (string [] args ) { var service = new ServiceCollection(); service.AddScoped<Controller>(); service.AddScoped<IStorage,StorageImp1>(); service.AddScoped<ILog,LogImp1>(); service.AddScoped<IConfig,ConfigImp1>(); using (var sp = service.BuildServiceProvider()) { var controller = sp.GetService<Controller>(); controller.Test(); } } class Controller { private readonly ILog log; private readonly IStorage storage; public Controller (ILog log, IStorage storage ) { this .storage = storage; this .log = log; } public void Test () { this .log.Log("开始上传" ); this .storage.Save("依赖注入测试" , "1.txt" ); this .log.Log("上传完毕" ); } } interface ILog { public void Log (string msg ) ; } class LogImp1 : ILog { public void Log (string msg ) { Console.WriteLine($"日志{msg} " ); } } interface IConfig { public string GetValue (string name ) ; } class ConfigImp1 : IConfig { public string GetValue (string name ) { return "\"hello_world\"" ; } } interface IStorage { public void Save (string content, string name ) ; } class StorageImp1 : IStorage { private readonly IConfig config; public StorageImp1 (IConfig config ) { this .config = config; } public void Save (string content, string name ) { string service = config.GetValue("service" ); Console.WriteLine($"向服务器{service} 上传文件名为{name} ,其内容为{content} " ); } } }
配置系统
配置读取顺序
配置中心服务器---->本地环境变量------>本地配置文件 (后者可将前者覆盖)
Json文件配置
1 2 3 4 5 { "name" : "WangMC" , "age" : "18" , "hobby" : { "sport" : "swimming" , "music" : "rock" } }
属性设置为 如果较新则复制
法一: NuGet安装Microsoft.Extensions.Configuration和Microsoft.Extensions.Configuration.Json包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 using Microsoft.Extensions.Configuration;using Microsoft.Extensions.DependencyInjection;using System.Threading.Channels;namespace ConsoleApp1 ;class MainClass { public static void Main (string [] args ) { var configBuilder = new ConfigurationBuilder(); configBuilder.AddJsonFile("config.json" , optional: true , reloadOnChange: true ); var configRoot = configBuilder.Build(); string name = configRoot["name" ]; string hobby_sport = configRoot.GetSection("hobby" )["sport" ]; Console.WriteLine($"Name: {name} , Age: {age} , Hobby_sport: {hobby_sport} " ); } }
法二: 绑定一个类 来进行配置的读取
NuGet安装Microsoft.Extensions.Configuration.Binder
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection;using System.Threading.Channels;namespace ConsoleApp1 ;class MainClass { public static void Main (string [] args ) { var configBuilder = new ConfigurationBuilder(); configBuilder.AddJsonFile("config.json" , optional: true , reloadOnChange: true ); var configRoot = configBuilder.Build(); var config = configRoot.Get<Config>(); string name = config.name; int age = config.age; Hobby hobby = config.hobby; string sprot = config.hobby.sport; } class Config { public string name { get ; set ; } public int age { get ; set ; } public Hobby hobby { get ; set ; } } class Hobby { public string sport { get ; set ; } public string music { get ; set ; } } }
选项方式读取
NuGet安装Microsoft.Extensions.Configuration Microsoft.Extensions.Configuration.Json包
Microsoft.Extensions.Configuration.Options Microsoft.Extensions.Configuration.Binder
读取配置时, DI要声明IOptions IOptionsMonitor IOptionsSnapshot等类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Options;namespace ConsoleApp1 ;class MainClass { public static void Main (string [] args ) { var services = new ServiceCollection(); services.AddScoped<TestController>(); var configBuild = new ConfigurationBuilder(); configBuild.AddJsonFile("config.json" ,optional:true ,reloadOnChange:true ); var configRoot = configBuild.Build(); services.AddOptions().Configure<Config>(e => configRoot.Bind(e)); using (var sp = services.BuildServiceProvider()) { int i = 4 ; while (i!=0 ) { var info = sp.GetRequiredService<TestController>(); info.Test(); i--; } } } class TestController { private readonly IOptionsSnapshot<Config> optConfig; public TestController (IOptionsSnapshot<Config> optConfig ) { this .optConfig=optConfig; } public void Test () { Console.WriteLine($"姓名:{optConfig.Value.name} " ); Console.WriteLine($"年龄:{optConfig.Value.age} " ); Console.WriteLine($"兴趣爱好:{optConfig.Value.hobby.sport} " ); Console.WriteLine($"兴趣爱好:{optConfig.Value.hobby.music} " ); } } class Config { public string name { get ; set ; } public int age { get ; set ; } public Hobby hobby { get ; set ; } } class Hobby { public string sport { get ; set ; } public string music { get ; set ; } } }
日志
级别: Trace<Debug<Information<Warning<Error<Critical
1. 输出到控制台
安装Microsoft.Extensions.Logging Microsoft.Extensions.Logging.Console
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Logging;using Microsoft.Extensions.Logging.Consolenamespace ConsoleApp1 ;class MainClass { public static void Main (string [] args ) { var services = new ServiceCollection(); services.AddLogging(logBuilder => { logBuilder.AddConsole(); logBuilder.SetMinimumLevel(LogLevel.Trace); }); services.AddScoped<Demo>(); using (var sp = services.BuildServiceProvider()) { var demo = sp.GetRequiredService<Demo>(); demo.Test(); } } class Demo { private readonly ILogger<Demo> logger; public Demo (ILogger<Demo> logger ) { this .logger = logger; } public void Test () { logger.LogWarning("this is a warning" ); logger.LogError("this is a Error" ); try { File.ReadAllText("A fake document" ); logger.LogDebug("Read Success!!" ); } catch (Exception ex) { logger.LogDebug(ex,"Read Failed!!" ); } } } }
2. 文本日志
使用NLog包
日志过滤和分类
1 2 3 <target xsi:type ="File" name ="logfile" fileName ="c:\temp\console-example.log" archiveAboveSize ="10000" maxArchiveFiles ="3" maxArchiveDays ="30" layout ="${longdate}|${level}|${message} |${all-event-properties} ${exception:format=tostring}" />
xsi:type="File":指定了目标的类型为File,这意味着日志消息将被写入到文件中。
name="logfile":为目标命名,这个名字在整个NLog配置中必须是唯一的,并且可以在日志规则中引用。
fileName="c:\temp\console-example.log":指定了日志文件的完整路径。日志消息将被写入到这个文件中。
archiveAboveSize="10000":这是一个可选参数,用于指定日志文件的大小阈值。当日志文件达到或超过这个大小时,NLog会将当前日志文件归档,并创建一个新的日志文件继续记录。单位是字节,这里设置为10000字节(大约10KB)。
maxArchiveFiles="3":这是一个可选参数,用于指定最大归档文件的数量。当达到这个数量时,NLog将开始删除最旧的归档文件,以便为新归档文件腾出空间。这里设置为3,意味着最多保留3个归档文件。
maxArchiveDays="30":其中 X 是一个整数,表示归档文件将被保留的天数。当归档文件创建后经过 X 天,NLog 将自动删除这些归档文件
layout="${longdate}|${level}|${message} |${all-event-properties} ${exception:format=tostring}":定义了日志消息的布局(layout)。布局是一个模板,它指定了日志消息的格式。以下是布局中各个元素的含义:
${longdate}:插入日志事件的时间戳。
${level}:插入日志事件的级别(例如:Info、Debug、Error等)。
${message}:插入日志事件的文本消息。
${all-event-properties}:插入所有事件属性的内容。
${exception:format=tostring}:如果日志事件中包含异常信息,则将其转换为字符串并插入到日志消息中。
3.结构化日志
使用Serilog包 安装Serilog.AspNetCore包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Logging;using Serilog;using Serilog.Formatting.Json;namespace ConsoleApp1 ;class MainClass { public static void Main (string [] args ) { IServiceCollection services = new ServiceCollection(); services.AddLogging(logBuilder => { Log.Logger = new LoggerConfiguration(). MinimumLevel.Debug(). Enrich.FromLogContext(). WriteTo.Console(new JsonFormatter()). CreateLogger(); services.AddSerilog(); }); services.AddScoped<Demo>(); services.AddScoped<Demo1>(); using (var sp = services.BuildServiceProvider()) { var demo = sp.GetRequiredService<Demo>(); var demo1 = sp.GetRequiredService<Demo1>(); demo1.Test(); demo.Test(); } } class Demo { private readonly ILogger<Demo> logger; public Demo (ILogger<Demo> logger ) { this .logger = logger; } public void Test () { logger.LogWarning("this is a warning" ); logger.LogError("this is a Error" ); logger.LogDebug("this is a debug" ); var Information = new { name = "WangMC" , Age = 18 }; string Hobby = "running" ; logger.LogDebug("Hello this is my informaiton {@Information},my hobby is {Hobby}" , Information, Hobby); } } class Demo1 { private readonly ILogger<Demo1> logger; public Demo1 (ILogger<Demo1> logger ) { this .logger = logger; } public void Test () { logger.LogWarning("这是一个警告" ); logger.LogError("这是一个错误" ); logger.LogDebug("这是一个debug" ); } } }
4.集中化日志
适合集群化部署 有N多服务器
Exceptionless 提供了现成的云服务 也可以本地部署(self hosting)