What's New in Blazor for .NET 8
Come find out about the future of Blazor in .NET 8! We'll explore all the upcoming features and improvements, including our effort to create a unified full stack web UI programming model that combines the strengths of client and server. We hope to see you there!
You will learn:
How Blazor is becoming the best option for full stack web development
How Blazor in .NET 8 will provide full flexibility to build web apps however works best for you
How to try out the latest Blazor features in .NET 8
Interceptor چیست؟
از زمان ارائهی NET 8 preview 6 SDK. به بعد، امکان رهگیری هر متدی از کدهای برنامه، به داتنت اضافه شدهاست؛ به همین جهت از واژهی Interceptor/رهگیر در اینجا استفاده میشود. خود تیم داتنت از این قابلیت در جهت بازنویسی پویای قسمتهایی از کدهای زیرساخت داتنت که از Reflection استفاده میکنند، با نگارشهای کامپایل شدهی مختص به برنامهی شما، کمک میگیرند. به این ترتیب سرعت و کارآیی برنامههای داتنت 8، بهبود قابل ملاحظهای را پیدا کردهاند. برای مثال ahead-of-time compilation (AOT) در داتنت 8 و ASP.NET Core 8x بر اساس این ویژگی پیاده سازی شدهاست. این ویژگی جدید، مکمل source generators است که در نگارشهای پیشین داتنت ارائه شده بود.
بررسی Interceptors با تهیهی یک مثال ساده
فرض کنید میخواهیم فراخوانی متد GetText زیر را رهگیری کرده و سپس آنرا با نمونهی دیگری جایگزین کنیم:
namespace CS8Tests; public class InterceptorsSample { public string GetText(string text) { return $"{text}, World!"; } }
namespace System.Runtime.CompilerServices; [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = false)] public sealed class InterceptsLocationAttribute : Attribute { public InterceptsLocationAttribute(string filePath, int line, int character) { } }
سپس فرض کنید فراخوانی متد GetText در فایل Program.cs برنامه به صورت زیر انجام شدهاست:
using CS8Tests; var example = new InterceptorsSample(); var text = example.GetText("Hello"); Console.WriteLine(text); //Hello, World!
در ادامه از این اطلاعات در رهگیر سفارشی زیر استفاده خواهیم کرد:
using System.Runtime.CompilerServices; namespace CS8Tests; public static class MyInterceptor { [InterceptsLocation("C:\\Path\\To\\CS8Tests\\Program.cs", 4, 20)] public static string InterceptorMethod(this InterceptorsSample example, string text) { return $"{text}, DNT!"; } }
اکنون اگر برنامه را اجرا کنیم ... با خطای زیر مواجه میشویم:
error CS9137: The 'interceptors' experimental feature is not enabled in this namespace. Add '<InterceptorsPreviewNamespaces>$(InterceptorsPreviewNamespaces);CS8Tests</InterceptorsPreviewNamespaces>' to your project.
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net8.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> <!--<NoWarn>Test001</NoWarn>--> <InterceptorsPreviewNamespaces>$(InterceptorsPreviewNamespaces);CS8Tests</InterceptorsPreviewNamespaces> </PropertyGroup> </Project>
Hello, DNT!
سؤال: آیا رهگیری انجام شده، در زمان کامپایل انجام میشود یا در زمان اجرا؟
برای این مورد میتوان به Low-Level C# code تولیدی مراجعه کرد. برای مشاهدهی یک چنین کدهایی میتوانید از منوی Tools->IL Viewer برنامهی Rider استفاده کرده و در برگهی ظاهر شده، گزینهی Low-Level C# آنرا انتخاب نمائید:
using CS8Tests; using System; using System.Runtime.CompilerServices; [CompilerGenerated] internal class Program { private static void <Main>$(string[] args) { Console.WriteLine(new InterceptorsSample().InterceptorMethod("Hello")); } public Program() { base..ctor(); } }
سؤال: آیا این قابلیت واقعا کاربردی است؟!
اکنون شاید این سؤال مطرح شود که ... واقعا چه کسی قرار است مسیر کامل یک فایل، شماره سطر و شماره ستون فراخوانی متدی را به اینگونه در اختیار سیستم رهگیری قرار دهد؟! آیا واقعا این قابلیت، یک قابلیت کاربردی و مناسب است؟!
اینجا است که اهمیت source generators مشخص میشود. توسط source generators دسترسی کاملی به syntax trees وجود دارد و همچنین یکسری اطلاعات تکمیلی مانند FilePath و سپس CSharpSyntaxNodeها که دسترسی به دادههای متد ()GetLocation را دارند که مکان دقیق سطر و ستونهای فراخوانیها را مشخص میکند.
کاربردهای فعلی رهگیرها در دات نت 8
در دات نت 8، این موارد با استفاده از رهگیرها بهینه سازی شده و سرعت آنها افزایش یافتهاند:
- فراخوانیهایی که تمام اطلاعات آنها در زمان کامپایل فراهم است، مانند Regex.IsMatch(@"a+b+") که از یک الگوی ثابت و مشخص استفاده میکند، رهگیری شده و پیاده سازی آن با کدی استاتیک، جایگزین میشود.
- در ASP.NET Minimal API، استفاده از lambda expressions جهت ارائهی تعاریفی مانند:
app.MapGet("/products", handler: (int? page, int? pageLength, MyDb db) => { ... })
- بهبود کارآیی foreach loops جهت استفاده از ریاضیات برداری و SIMD در صورت امکان.
- بهبود کارآیی تزریق وابستگیها، زمانیکه به تعاریف مشخصی مانند ()<provider.Register<MyService ختم میشود.
- بجای استفاده از expression trees در زمان اجرای برنامه، اکنون میتوان کدهای SQL معادل را در زمان کامپایل برنامه تولید کرد.
- بهبود کارآیی Serializers، زمانیکه از یک نوع مشخص مانند ()<Serialize<MyType استفاده میشود و کامپایلر میتواند آنرا با کدهای زمان کامپایل، جایگزین کند.
محدودیتهای رهگیرها در داتنت 8
- رهگیرهای داتنت 8 فقط با متدها کار میکنند.
- مسیر ارائه شده حتما باید یک مسیر کامل و مشخص باشد. یعنی اگر این قطعه کد، به سیستم دیگری منتقل شود، کامپایل نخواهد شد و امکان ارائهی مسیرهای نسبی وجود ندارد.
- امضای متدها، حتما باید یکی باشد. یعنی نمیتوان یک رهگیر جنریک را تعریف کرد.
انتشار اولین پیشنمایش ASP.NET 8
.NET 8 Preview 1 is now available! This is the first preview of the next major version of .NET, which will include the next wave of innovations for web development with ASP.NET Core.
In .NET 8 we plan to make broad investments across ASP.NET Core. Below are some of the areas we plan to focus on:
مسیر راه نگارشهای مختلف دات نت
NET 8 Preview 3. منتشر شد
.NET 8 Preview 3 is now available. It includes changes to build paths, workloads, Microsoft.Extensions, and containers. It also includes performance improvements in the JIT, for Arm64, and dynamic PGO. If you missed the March preview, you may want to read the Preview 2 post.
A .NET guideline specifies that an application should never throw a NullReferenceException
. However, many applications and libraries do. The NullReferenceException
is the most common exception happening. That’s why C# 8 tries to get rid of it. With C# 8, reference types are not null be default. This is a big change, and a great feature. However, what about all the legacy code? Can old libraries be used with C# 8 applications, and can C# 7 applications make use of C# 8 libraries?
This article demonstrates how C# 8 allows mixing old and new assemblies.
بازهها و الگوهای بازگشتی در C# 8
- C# 8 Adds Ranges and Recursive Patterns
- Ranges easily define a sequence of data, replacing the Enumberable.Range()
- Recursive Patterns brings an F#-like construct to C#
- Recursive Patterns is an awesome feature, it giving you the flexibility to testing the data against a sequence of conditions and performing further computations based on the condition met.
- Ranges is very useful to generate sequences of numbers in the form of a collection or a list.
در این حالت اگر کدی، شروع به استفادهی از یک چنین عضوهای آزمایشی کند، یک خطای زمان کامپایل رخ میدهد؛ مگر اینکه آن قطعه کد نیز دقیقا با همین ویژگی مزین شود. در اینجا میتوان نوعها، اسمبلیها و حتی اعضای آنها را آزمایشی تعریف کرد. اگر کل یک نوع را به صورت آزمایشی معرفی کنیم، تمام اعضای آن هم آزمایشی خواهند بود.
بررسی ویژگی Experimental با یک مثال
در ادامه نحوهی اعمال ویژگی Experimental را به همراه یک diagnosticId که به کل یک کلاس اعمال شدهاست، مشاهده میکنید. از این diagnosticId در حین تولید متن خطاها و یا برای شناسایی آنها، استفاده میشود:
using System.Diagnostics.CodeAnalysis; namespace CS8Tests; [Experimental(diagnosticId: "Test001")] public class ExperimentalAttributeDemo { public void Print() { Console.WriteLine("Hello Experimental Attribute"); } }
var experimentalAttributeDemo = new ExperimentalAttributeDemo();
error Test001: 'CS8Tests.ExperimentalAttributeDemo' is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
الف) غیرفعال کردن سراسری گزارش این نوع خطاها در فایل csproj. برنامه:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net8.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> <NoWarn>Test001</NoWarn> </PropertyGroup> </Project>
ب) غیرفعال کردن موضعی آن، صرفا در محل استفاده
برای غیرفعال کردن محلی این بررسی، تنها کافی است با استفاده از pragma warning# یکبار آنرا غیرفعال کرده و پس از پایان کار، مجددا آنرا فعال کنیم:
#pragma warning disable Test001 var demo = new ExperimentalAttributeDemo(); #pragma warning restore Test001
و اگر این مثال را کمی پیچیدهتر کنیم، به حالت زیر میرسیم:
using System.Diagnostics.CodeAnalysis; namespace CS8Tests; [Experimental(diagnosticId: "Test001")] public class ExperimentalAttributeDemo { [Experimental(diagnosticId: "Test002")] public void Print() { Console.WriteLine("Hello Experimental Attribute"); } }
var demo = new ExperimentalAttributeDemo(); demo.Print();
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net8.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> <NoWarn>Test001,Test002</NoWarn> </PropertyGroup> </Project>
#pragma warning disable Test001,Test002 var demo = new ExperimentalAttributeDemo(); demo.Print(); #pragma warning restore Test001,Test002