روش تعریف خواص سفارشی 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... }
FastReport سورس باز شد
We are very pleased to announce the launch of our Open Source project - Fast Report Open Source.
We are hoping to develop a friendly community of .Net Core developers who will share our eagerness to create fast, powerful and convenient reporting tool for Windows, Windows Server, Linux and MacOS.
We also encourage you to be a part of the global reporting team! Join us on GitHub: github.com/FastReports/FastReport
Android 15 منتشر شد
Today we're releasing Android 15 and making the source code available at the Android Open Source Project (AOSP). Android 15 will be available on supported Pixel devices in the coming weeks, as well as on select devices from Samsung, Honor, iQOO, Lenovo, Motorola, Nothing, OnePlus, Oppo, realme, Sharp, Sony, Tecno, vivo, and Xiaomi in the coming months.