با توجه به آخرین نگارشهای موجود Angular و React، انتخاب شما برای انجام یک پروژه بزرگ کدام است؟
This is a defense of the most prolific and dedicated public servant that has graced the world in my lifetime. One man has added hundreds of billions, if not trillions of dollars of value to the global economy. This man has worked tirelessly for the benefit of everyone around him. It is impossible to name a publicly traded company that has not somehow benefited from his contributions, and many have benefited to the tune of billions. In return for the countless billions of wealth that people made from the fruits of his labor, he was rewarded with poverty and ridicule. Now that the world is done taking from him, they are heading to the next step of vilifying him as incompetent.
We are thrilled to announce the highly anticipated .NET Conf 2024, a free, three-day virtual developer event celebrating the release of .NET 9. Co-organized by the .NET community and Microsoft, this annual tradition continues to grow, and we’re more excited than ever to bring you the latest innovations in .NET. Mark your calendars for November 12th to 14th, 2024, and prepare to be inspired by a wealth of knowledge, creativity, and community engagement.
اضافه شدن JIT به PostgreSQL 11
روش تعریف خواص سفارشی MSBuild در پروژهی Source Generator
در مثال همین سری، به پوشهی NotifyPropertyChangedGenerator مراجعه کرده و فایل جدید NotifyPropertyChangedGenerator.props را با محتوای زیر به آن اضافه میکنیم:
<Project> <ItemGroup> <CompilerVisibleProperty Include="SourceGenerator_CustomRootNamespace"/> </ItemGroup> </Project>
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <GeneratePackageOnBuild>true</GeneratePackageOnBuild> <!-- Generates a package at build --> <IncludeBuildOutput>false</IncludeBuildOutput> <!-- Do not include the generator as a lib dependency --> </PropertyGroup> <ItemGroup> <!-- Package the generator in the analyzer directory of the nuget package --> <None Include="$(OutputPath)\$(AssemblyName).dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false"/> <!-- Package the props file --> <None Include="NotifyPropertyChangedGenerator.props" Pack="true" PackagePath="build" Visible="true"/> </ItemGroup> </Project>
یک نکتهی مهم! اگر بخواهیم مستقیما از پروژهی source generator خود مثلا در پروژهی NotifyPropertyChangedGenerator.Demo این سری همانند قبل استفاده کنیم، تنظیمات ذکر شدهی در فایل props. فوق، در آن قابل دسترسی نخواهند بود و با پروسهی build یکی نمیشوند. تنظیماتی که تا اینجا ذکر شدند، فقط مخصوص بستهی نیوگت نهایی است. برای استفادهی مستقیم از آنها در پروژهی Demo، نیاز است یکبار دیگر محتویات props. تولید کنندهی کد را داخل فایل csproj. پروژهی Demo، تعریف کرد. یا میتوان از روش استفاده از فایل ویژهی Directory.Build.props و قابلیتهای ارثبری آن استفاده کرد. یعنی یک فایل Directory.Build.props را در بالاترین سطح ممکن قرار داد و CompilerVisiblePropertyها را در آن تعریف کرد تا در تمام پروژههای برنامه قابل دسترسی شوند.
روش تعریف خواص سفارشی MSBuild در پروژهی استفاده کننده از Source Generator
در مثال این سری چون از بستهی نیوگت تولید کنندهی کد استفاده نمیکنیم، نیاز است خاصیت سفارشی تعریف شده را یکبار دیگر داخل فایل csproj. پروژهی Demo تعریف کنیم. پس از آن میتوان این خاصیت را در قسمت PropertyGroup مقدار دهی کرد:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <SourceGenerator_CustomRootNamespace>ThisIsTest</SourceGenerator_CustomRootNamespace> </PropertyGroup> <ItemGroup> <CompilerVisibleProperty Include="SourceGenerator_CustomRootNamespace"/> </ItemGroup> </Project>
روش دسترسی به مقدار خاصیت سفارشی MSBuild در پروژهی Source Generator
پس از این مقدمات، خواص عمومی MSBuild از طریق خاصیت AnalyzerConfigOptions.GlobalOptions و متد TryGetValue آن با فرمول زیر قابل دسترسی هستند. قسمت build_property ثابت بوده و جزو موارد توکار MSBuild است:
internal static class SourceGeneratorContextExtensions { public static string GetMSBuildProperty( this GeneratorExecutionContext context, string property, string defaultValue = "") { return !context.AnalyzerConfigOptions.GlobalOptions.TryGetValue($"build_property.{property}", out var value) ? defaultValue : value; } }
[Generator] public class NotifyPropertyChangedGenerator : ISourceGenerator { public void Initialize(GeneratorInitializationContext context) { } public void Execute(GeneratorExecutionContext context) { var customRootNamespace = context.GetMSBuildProperty("SourceGenerator_CustomRootNamespace", "Test");
معرفی خاصیت ویژهی AdditionalFiles
تا اینجا روش تعریف یک خاصیت جدید MSBuild و روش دسترسی به آنرا بررسی کردیم. خاصیت توکاری به نام AdditionalFiles نیز در MSBuild تعریف شدهاست که در پروژههای Source Generator جهت دسترسی به فایلها و محتوای آنها قابل استفاده است. برای نمونه میتوان در فایل csproj. پروژهی Demo تعریف زیر را ارائه کرد:
<Project Sdk="Microsoft.NET.Sdk"> <ItemGroup> <AdditionalFiles Include="file1.txt" Visible="false"/> </ItemGroup> </Project>
خاصیت Visible در اینجا مشخص میکند که آیا file1.txt در IDE، در کنار لیست سایر فایلها نمایش داده شود یا خیر.
امکان تعریف خواص سفارشی بر روی AdditionalFiles
فرض کنید علاقمندیم خاصیت ویژهای را به AdditionalFiles اضافه کنیم؛ برای مثال به نام SourceGenerator_EnableLogging مانند مثال زیر:
<Project Sdk="Microsoft.NET.Sdk"> <ItemGroup> <AdditionalFiles Include="file2.txt" SourceGenerator_EnableLogging="true" Visible="false"/> </ItemGroup> </Project>
الف) فایل NotifyPropertyChangedGenerator.props تعریف شده را به صورت زیر تکمیل میکنیم:
<Project> <ItemGroup> <CompilerVisibleProperty Include="SourceGenerator_CustomRootNamespace"/> <CompilerVisibleProperty Include="SourceGenerator_EnableLogging"/> <CompilerVisibleItemMetadata Include="AdditionalFiles" MetadataName="SourceGenerator_EnableLogging"/> </ItemGroup> </Project>
ب) در فایل csproj. پروژهی Demo، از این خواص و متادیتاها استفاده میکنیم:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <SourceGenerator_EnableLogging>true</SourceGenerator_EnableLogging> </PropertyGroup> <ItemGroup> <CompilerVisibleProperty Include="SourceGenerator_EnableLogging"/> <CompilerVisibleItemMetadata Include="AdditionalFiles" MetadataName="SourceGenerator_EnableLogging"/> <AdditionalFiles Include="file1.txt" Visible="false"/> <!-- logging will be controlled by default, or global value --> <AdditionalFiles Include="file2.txt" SourceGenerator_EnableLogging="true" Visible="false"/> <!-- always enable logging for this file --> <AdditionalFiles Include="file3.txt" SourceGenerator_EnableLogging="false" Visible="false"/> <!-- never enable logging for this file --> </ItemGroup> </Project>
ج) برای خواندن این خواص در پروژهی Source generator به صورت زیر عمل میشود:
internal static class SourceGeneratorContextExtensions { public static string GetAdditionalFilesOption( this GeneratorExecutionContext context, AdditionalText additionalText, string property, string defaultValue = "") { return !context.AnalyzerConfigOptions.GetOptions(additionalText) .TryGetValue($"build_metadata.AdditionalFiles.{property}", out var value) ? defaultValue : value; } }
- روش تامین AdditionalText این متد را نیز در مثال زیر مشاهده میکنید که حاصل ایجاد حلقهای بر روی context.AdditionalFilesهای دریافتی است:
[Generator] public class NotifyPropertyChangedGenerator : ISourceGenerator { public void Initialize(GeneratorInitializationContext context) { } public void Execute(GeneratorExecutionContext context) { var customRootNamespace = context.GetMSBuildProperty("SourceGenerator_CustomRootNamespace", "Test"); var globalLoggingSwitch = context.GetMSBuildProperty("SourceGenerator_EnableLogging", "false"); var emitLoggingGlobal = globalLoggingSwitch.Equals("true", StringComparison.OrdinalIgnoreCase); foreach (var file in context.AdditionalFiles) { var perFileLoggingSwitch = context.GetAdditionalFilesOption(file, "SourceGenerator_EnableLogging"); var emitLogging = string.IsNullOrWhiteSpace(perFileLoggingSwitch) ? emitLoggingGlobal // allow the user to override the global logging on a per-file basis : perFileLoggingSwitch.Equals("true", StringComparison.OrdinalIgnoreCase); // add the source with or without logging... }