There is no question that the Polly library has had a big impact on the .NET community in providing useful resilience and transient fault handling policies in an accessible way to millions of projects.
تست کدهای سیشارپ بصورت آنلاین
SharpLab (previously known as TryRoslyn)
SharpLab is a .NET code playground that shows intermediate steps and results of code compilation
Languages
SharpLab supports three source languages:
- C#
- Visual Basic
- F#
کتابخانه Brighter
The Brighter project is up on GitHub incudes a bunch of libraries and examples that you can pull in to support CQRS architectural styles in .NET.
نمونه از پیاده سازی این کتابخانه در Mvc Core
public class TestController { private readonly ILogger<TestController> _logger; public TestController(ILogger<TestController> logger) { _logger = logger; } [HttpGet("/")] public string Get() { _logger.LogInformation("hello world"); return "Hello world!"; } }
اگر یک چنین برنامهای را به دات نت 6 ارتقاء دهید، با پیام اخطار زیر مواجه خواهید شد:
CA1848: For improved performance, use the LoggerMessage delegates instead of calling LogInformation
استفادهی گسترده از source generators در دات نت 6
source generators، امکان مداخله در عملیات کامپایل برنامه را میسر کرده و امکان تولید کدهای پویایی را در زمان کامپایل، فراهم میکنند. هرچند این قابلیت به همراه دات نت 5 ارائه شدند، اما تا زمان دات نت 6 استفادهی گستردهای از آن در خود دات نت صورت نگرفت. موارد زیر، تغییراتی است که بر اساس source generators در دات نت 6 رخ دادهاند:
- source generators مخصوص ILogger (موضوع این بحث؛ یعنی LoggerMessage source generator)
- source generators مخصوص System.Text.Json تا سربار تبدیل به JSON و یا برعکس کمتر شود.
- بازنویسی مجدد پروسهی کامپایل Blazor/Razor بر اساس source generators، بجای روش دو مرحلهای قبلی که امکان Hot Reload را فراهم کردهاست.
نوشتن یک source generator هرچند ساده نیست، اما چون نیاز به reflection را به حداقل میرساند، میتواند تغییرات کارآیی بسیار مثبتی را به همراه داشته باشد.
توصیه به استفاده از LoggerMessage.Define در دات نت 6
ILogger به همراه قابلیتهایی مانند structural logging نیز هست که امکان فرمت بهتر پیامهای ثبت شده را میسر میکند تا توسط برنامههای جانبی که قرار است این لاگها را پردازش کنند، به سادگی قابل خواندن باشند. برای مثال رکورد زیر را در نظر بگیرید:
public record Person (int Id, string Name);
var person = new Person(123, "Test");
_logger.LogInformation("hello to {Person}", person);
info: TestController[0] hello world to Person { Id = 123, Name = Test }
اگر در اینجا مانند مثال زیر از string interpolation استفاده شود:
_logger.LogInformation($"hello world to {person}"); // Using interpolation instead of structured logging
- ویژگی «لاگهای ساختار یافته» را از دست میدهیم و دیگر توسط نرم افزارهای ثالث لاگ خوان، به سادگی پردازش نخواهند شد.
- ویژگی «قالب ثابت» پیام را نیز از دست خواهیم داد که باز هم یافتن پیامهای مشابه را در بین انبوهی از لاگهای رسیده مشکل میکند.
- کار serialization شیء ارسالی به آن، پیش از عملیات ثبت وقایع رخ میدهد. اما ممکن است سطح لاگ سیستم در این حد نباشد و اصلا این پیام لاگ نشود. در این حالت یک کار اضافی صورت گرفته و بر روی کارآیی برنامه تاثیر منفی خواهد گذاشت.
برای جلوگیری از serialization و همچنین تخصیص حافظهی اضافی و مشکلات عدم ساختار یافته بودن لاگها، توصیه شدهاست که ابتدا سطح لاگ مدنظر بررسی شود و همچنین از string interpolation استفاده نشود:
if (_logger.IsEnabled(LogLevel.Information)) { _logger.LogInformation("hello world to {Person}", person); }
مشکل دیگر لاگهای ساختار یافته، امکان فراموش کردن یکی از پارامترها است که با یک خطای زمان اجرا گوشزد خواهد شد؛ مانند مثال زیر:
_logger.LogInformation("hello world to {Person} because {Reason}", person);
private static readonly Action<ILogger, Person, Exception?> _logHelloWorld = LoggerMessage.Define<Person>( logLevel: LogLevel.Information, eventId: 0, formatString: "hello world to {Person}");
اکنون روش فراخوانی این Action با کارآیی بالا به صورت زیر است:
[HttpGet("/")] public string Get() { var person = new Person(123, "Test"); _logHelloWorld(_logger, person, null); return "Hello world!"; }
معرفی [LoggerMessage] source generator در دات نت 6
هرچند LoggerMessage.Define، مزایای قابل توجهی مانند کش شدن قالب لاگ، عدم نیاز به بررسی ضرورت لاگ شدن پیام و ارسال تعداد پارامترهای صحیح را به همراه دارد، اما ... کار کردن با آن مشکل است و برای کار با آن باید کدهای زیادی را نوشت. به همین جهت با استفاده از قابلیت source generators، امکان تولید خودکار این نوع کدها در زمان کامپایل برنامه پیشبینی شدهاست:
public partial class TestController { [LoggerMessage(0, LogLevel.Information, "hello world to {Person}")] partial void LogHelloWorld(Person person); }
ویژگی partial method، امکان تعریف یک متد را در یک فایل و سپس ارائهی پیاده سازی آنرا در فایلی دیگر میسر میکند که البته در اینجا آن فایل دیگر، توسط source generator تولید میشود.
باید دقت داشت که در اینجا TestController را نیز باید به صورت partial تعریف کرد تا آن نیز قابلیت بسط در چند فایل را پیدا کند. همچنین متد فوق را به صورت static partial void نیز میتوان نوشت.
یکی از مزایای کار با source generator که خودش در اصل یک آنالایزر هم هست، بررسی تعداد پارامترهای ارسالی و تعریف شدهاست:
[LoggerMessage(0, LogLevel.Information, "hello world to {Person} with a {Reason}")] partial void LogHelloWorld(Person person);
در این روش، امکان ذکر پارامتر اختیاری LogLevel هم وجود دارد؛ اگر نیاز است مقدار آن به صورت پویا تغییر کند:
[LoggerMessage(Message = "hello world to {Person}")] partial void LogHelloWorld(LogLevel logLevel, Person person);
Microsoft چه تعداد مشتری دارد؟
بررسی Pythonnet
مجموعه Awesome .NET Core
لیست awesome-analyzers
Build Accelerator, BuildXL for short, is a build engine originally developed for large internal teams at Microsoft, and owned by the Tools for Software Engineers team, part of the Microsoft One Engineering System internal engineering group. Internally at Microsoft, BuildXL runs 30,000+ builds per day on monorepo codebases up to a half-terabyte in size with a half-million process executions per build, using distribution to thousands of datacenter machines and petabytes of source code, package, and build output caching. Thousands of developers use BuildXL on their desktops for faster builds even on mega-sized codebases.