首页 > 其他分享 >.Net8新特性

.Net8新特性

时间:2023-11-25 16:12:59浏览次数:40  
标签:Console string app 特性 logContext Net8 var NET

本文整理.Net8新特性的使用方法。
当前包括:

  • Route ShortCircuit
  • Exception Throw Helper
  • HttpLoggingMiddleware 的改进
  • C# 12 中的 InlineArray 特性

Route ShortCircuit

有些请求,如浏览器会自动请求 favicon.ico,这些请求即使很简单,往往也会完整地运行中间件管道,但实际上可能并不需要,在 .NET 8 中引入了一个 Route ShortCircuit 的功能,也就是路由短路,可以在处理结束之后马上中断请求,不再执行后面的中间件了,这样会使得这样的路由或者 API 更加高效。

在 route 后添加 ShortCircut() 来启用,使用方法如下:

var builder = WebApplication.CreateSlimBuilder(args);

var app = builder.Build();
app.Use(async (HttpContext context, RequestDelegate next) =>
{
    context.Response.Headers["Value"] = "123";
    await next(context);
});
app.MapGet("/", () => "Hello .NET 8!");

// ShortCircuit
app.MapGet("/short-circuit", () => "Short circuiting!").ShortCircuit();
app.MapGet("/short-circuit-status", () => "Short circuiting!")
            .ShortCircuit(401);
// MapShortCircuit
app.MapShortCircuit(404, "robots.txt", "favicon.ico");
app.MapShortCircuit(403, "admin");

await app.RunAsync();

Exception Throw Helper

在 .NET 6 中,引入了一个 ArgumentNullException.ThrowIfNull(object? argument, string? paramName = default) 的方法,在 .NET 7/8 中引入了更多的支持,我们可以在代码里使用这些 exception helper 来简化一些代码。

常用的 Argument exception:

ArgumentNullExceptionSample(null);

ArgumentExceptionThrowIfNullOrEmptySample(null);
ArgumentExceptionThrowIfNullOrEmptySample(string.Empty);

ArgumentExceptionThrowIfNullOrWhiteSpaceSample(null);
ArgumentExceptionThrowIfNullOrWhiteSpaceSample(string.Empty);
ArgumentExceptionThrowIfNullOrWhiteSpaceSample(" ");

public static void ArgumentNullExceptionSample(string? value)
{
    InvokeHelper.TryInvoke(() => ArgumentNullException.ThrowIfNull(value));
}

public static void ArgumentExceptionThrowIfNullOrEmptySample(string? value)
{
    InvokeHelper.TryInvoke(() => ArgumentException.ThrowIfNullOrEmpty(value));
}

public static void ArgumentExceptionThrowIfNullOrWhiteSpaceSample(string? value)
{
    InvokeHelper.TryInvoke(() => ArgumentException.ThrowIfNullOrWhiteSpace(value));
}

ArgumentNullException.ThrowIfNull(object? obj, string? paramName = default) 是 .NET 6 开始支持的

在 .NET 7 里支持了指针的判断 ArgumentNullException.ThrowIfNull(void* argument, string? paramName = default)(not CLS-compliant)

.NET 7 还引入了 ArgumentException.ThrowIfNullOrEmpty(string? value, string? paramName = default), 增加判断空字符串的场景

.NET 8 引入了 ArgumentException.ThrowIfNullOrWhiteSpace(string? value, string? paramName = default) 增强了判断空字符串的场景

HttpLoggingMiddleware 的改进

.NET 6 开始引入了一个 http logging 的中间件,我们可以借助于 http logging 的中间件记录请求和响应的信息,但是扩展性不是很强,在 .NET 8 版本中进行了一些优化,引入了一些新的配置和 HttpLoggingInterceptor 使得它更加容易扩展了

HttpLoggingFields 中新增了一个 Duration 枚举值,会记录请求处理的耗时

在 HttpLoggingOptions 中增加了一个 CombineLogs 的配置,默认是 false,默认 request/response/duration 的 log 都是分开的,配置为 true 之后就会合并成一条日志。

HttpLoggingInterceptor

.NET 8 还引入了 IHttpLoggingInterceptor,借助于此可以更好的扩展 http logging

可以根据 Request 或者 Response 信息来动态地调整要记录的 field 或者动态调整 RequestBodyLogLimit/ResponseBodyLogLimit

来看一个 HttpLoggingInterceptor 示例:

file sealed class MyHttpLoggingInterceptor: IHttpLoggingInterceptor
{
    public ValueTask OnRequestAsync(HttpLoggingInterceptorContext logContext)
    {
        if (logContext.HttpContext.Request.Path.Value?.StartsWith("/req-") == true)
        {
            logContext.LoggingFields = HttpLoggingFields.ResponsePropertiesAndHeaders;
            logContext.AddParameter("req-path", logContext.HttpContext.Request.Path.Value);
        }
        
        return ValueTask.CompletedTask;
    }

    public ValueTask OnResponseAsync(HttpLoggingInterceptorContext logContext)
    {
        if (logContext.HttpContext is { Response.StatusCode: >=200 and < 300, Request.Path.Value: "/hello" })
        {
            logContext.TryDisable(HttpLoggingFields.All);
        }
        return ValueTask.CompletedTask;
    }
}

使用示例如下,使用 AddHttpLoggingInterceptor() 来注册:

var builder = WebApplication.CreateSlimBuilder(args);
builder.Services.AddControllers();
builder.Services.AddHttpLogging(options =>
{
    options.LoggingFields = HttpLoggingFields.All;
    options.CombineLogs = true;
});
builder.Services.AddHttpLoggingInterceptor<MyHttpLoggingInterceptor>();

var app = builder.Build();
app.UseHttpLogging();
app.MapGet("/hello", () => "Hello");
app.MapGet("/crash", () => Results.BadRequest());
app.MapGet("/req-intercept", () => "Hello .NET 8");
app.MapControllers();
await app.RunAsync();

可以看到每个请求的 log 输出的结果都有所不同,第一个请求虽然我们设置了 ogContext.TryDisable(HttpLoggingFields.All) 但是还是有输出结果这是因为 httpLogging 目前的实现就是这样,在 Response 里处理的时候 request 信息已经被记录好了,详细可以参考 http logging middleware 的 实现

如果想要完全 disable 需要在 OnRequestAsync 方法里处理

public ValueTask OnRequestAsync(HttpLoggingInterceptorContext logContext)
{
    if ("/no-log".Equals(logContext.HttpContext.Request.Path.Value, StringComparison.OrdinalIgnoreCase))
    {
        logContext.LoggingFields = HttpLoggingFields.None;
    }
    //
    return ValueTask.CompletedTask;
}

这样请求就不会有日志打印了

最后一个 req-intercept 在 request 的处理中设置了 ResponsePropertiesAndHeaders 并且加了一个自定义的 Parameter 从输出结果可以看到有输出到日志

More
大家可以自己尝试一下,比之前会好用一些,但是觉得还是有所欠缺

比如日志级别目前还都是 Information 不能动态的改变日志级别

另外就是前面提到的即使使用 CombineLogs 在 response 中设置为 HttpLoggingFields.None 时,依然会记录 request 信息,希望后面还会继续优化一下

C# 12 中的 InlineArray 特性

C# 12 引入了一个 InlineArray 特性,利用这一特性,我们可以更方便地类数组的结构体,可以代替原来要使用非安全代码的 fixed size buffer

[System.Runtime.CompilerServices.InlineArray(10)]
file struct MyArray
{
    // required
    private int _element;
}

使用 InlineArray 需要指定 size,也就是 array 的长度,并且我们需要声明一个字段

使用示例如下:

var arr = new MyArray();
for (var i = 0; i < 10; i++)
{
    arr[i] = i;
}
foreach (var i in arr)
{
    Console.Write(i);
    Console.Write(",");
}

Console.WriteLine();

ReadOnlySpan<int> span = arr;
foreach (var i in span)
{
    Console.Write(i);
    Console.Write(",");
}

Console.WriteLine();

foreach (var i in arr[^2..])
{
    Console.Write(i);
    Console.Write(",");
}
Console.WriteLine();

Console.WriteLine(arr[^1]);

// error CS0021: Cannot apply indexing with [] to an expression of type 'MyArray'
// if (arr is [0,1,..])
//     Console.WriteLine("StartsWith 0, 1");

if (span is [0,1,..])
    Console.WriteLine("StartsWith 0, 1");

// error CS9174: Cannot initialize type 'MyArray' with a collection expression because the type is not constructible.
// arr = [1, 2, 3, 4, 5];

span = [1,2,3,4,5];
foreach (var item in span)
{
    Console.Write(item);
    Console.Write(",");
}

运行结果:

0,1,2,3,4,5,6,7,8,9,
0,1,2,3,4,5,6,7,8,9,
8,9,
9
StartsWith 0, 1
1,2,3,4,5,

从这个示例可以看得出来,我们可以像使用数组一样使用,同时我们可以直接隐式转换成 Span 和 ReadOnlySpan,
并且可以使用 Index 和 Range 操作符,但是目前暂时不能直接使用集合表达式和 list pattern,但是我们可以转成 span 之后再使用
文章来源

标签:Console,string,app,特性,logContext,Net8,var,NET
From: https://www.cnblogs.com/LifelongLearning/p/17855615.html

相关文章

  • .NET8极致性能优化Non-GC Heap
    前言.NET8里面JIT引入了一个新的机制,叫做Non-GCHeap。JIT可以确保相关对象分配在Non-GCHeap上,该堆像其名称一样,不受GC管理。JIT需要保证这个对象没有被GC引用,并且在这个对象的生命周期内一直是根对象(不会被GC消灭的对象)的状态。原文:.NET8极致性能优化Non-GCHeap概述为什......
  • ConfigureAwait in .NET8
    ConfigureAwaitin.NET8ConfigureAwait(true)和ConfigureAwait(false)首先,让我们回顾一下原版ConfigureAwait的语义和历史,它采用了一个名为continueOnCapturedContext的布尔参数。当对任务(Task、Task<T>、ValueTask或ValueTask<T>)执行await操作时,其默认行为是捕获“上......
  • GeminiDB新特性:让Redis广告频控爱不释手的exHASH
    本文分享自华为云社区《GeminiDB新特性:让Redis广告频控爱不释手的exHASH》,作者:GeminiDB-Redis博客。exHash类型是一种支持Field过期的新型数据类型,它在原先的Hash类型基础上进行了扩展:在支持Hash类型的通用功能以外,exHash类型还支持为Field设置过期时间和版本,增强了数据结构的灵......
  • .NET8:快速集成Rapid.NET三维控件
    .NET8正式版本发布了,AnyCADRapid.NET针对.NET8进行了升级和优化。本文以WPF项目为例介绍在.NET8中使用AnyCADRapid.NET三维控件。1从.NET6升级若之前使用NET6升级到.NET8,升级过程非常简单,升级到AnyCADRapid.NET最新版本后,仅需要更改以下两处:(1).csproj文件<TargetFramewor......
  • RHEL8新特性介绍及安装
    ......
  • MySQL8.0新特性
    MySql8的其他新特性1.MySQL8新特性概述MySQL从5.7版本直接跳跃发布了8.0版本,可见这是一个令人兴奋的里程碑版本。MySQL8版本在功能上做了显著的改进与增强,开发者对MySQL的源代码进行了重构,最突出的一点是多MySQLOptimizer优化器进行了改进。不仅在速度上得到了改善,还为......
  • 算法的奥秘:种类、特性及应用详解(算法导论笔记1)
    原文链接算法,是计算机科学领域的灵魂,是解决问题的重要工具。在算法的世界里,有着各种各样的种类和特性。今天,我将带各位踏上一段探索算法种类的旅程,分享一些常见的算法种类,并给出相应的实践和案例分析。希望通过本文的介绍,能够帮助您更好地理解和应用这些算法,提高解决问题的能力。......
  • Java8新特性lambda学习
    Lambda表达式Lambda是一个匿名函数,我们可以把Lambda表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。使用它可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。本质:作为函数式接口的实例,没有接口就没意义了.//简单......
  • .NET8.0 AOT 经验分享 - 专项测试各大 ORM 是否支持
    AOT特点发布和部署本机AOT应用具有以下优势:最大程度减少磁盘占用空间:使用本机AOT发布时,将生成一个可执行文件,其中仅包含支持程序所需的外部依赖项的代码。减小的可执行文件大小可能会导致:较小的容器映像,例如在容器化部署方案中。缩短了较小映像的部署时间。缩短启动......
  • postgresql 16主要新特性
    继postgresql15新特性后,pg16已经发布,这个版本的主要特性如下:1、逻辑复制支持级联,不一定要从primary开始;2、逻辑复制支持订阅自己,也就是真正的双主可以通过逻辑复制内置订阅实现了,不需要依赖三方,如pglogical3、copy性能提升明显,某些场景下300%4、SIMD支持数组和json、子事务搜......