کاهش تعداد بار تعریف using ها در C# 10.0 و NET 6.0.
نویسنده: وحید نصیری
تاریخ: ۱۴۰۰/۰۷/۲۷ ۱۱:۳۰
آدرس: www.dntips.ir
| مطالب | ۳۶۹۴ |
| نویسندگان | ۲۷۶ |
| گروههای مطالب | ۱۰۲۴ |
| نقشههای راه | ۱۱۹ |
| دورهها | ۱۴ |
| اشتراکها | ۱۷۹۱۴ |
// See https://aka.ms/new-console-template for more information
Console.WriteLine("Hello, World!"); <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project> global using System;
global using static System.Console;
<ImplicitUsings>enable</ImplicitUsings>
// <auto-generated/> global using global::System; global using global::System.Collections.Generic; global using global::System.IO; global using global::System.Linq; global using global::System.Net.Http; global using global::System.Threading; global using global::System.Threading.Tasks;
// <autogenerated /> global using global::System; global using global::System.Collections.Generic; global using global::System.IO; global using global::System.Linq; global using global::System.Net.Http; global using global::System.Threading; global using global::System.Threading.Tasks; global using global::System.Net.Http.Json; global using global::Microsoft.AspNetCore.Builder; global using global::Microsoft.AspNetCore.Hosting; global using global::Microsoft.AspNetCore.Http; global using global::Microsoft.AspNetCore.Routing; global using global::Microsoft.Extensions.Configuration; global using global::Microsoft.Extensions.DependencyInjection; global using global::Microsoft.Extensions.Hosting; global using global::Microsoft.Extensions.Logging;
<ItemGroup> <Import Remove="System.Threading" /> <Import Include="Microsoft.Extensions.Logging" /> </ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net472'"> </ItemGroup>
global using DT = System.DateTime;
global using App.Models; global using static System.Console; global using DT = System.DateTime;
<ItemGroup>
<Using Include="App.Models"/>
<Using Include="System.Console" Static="True" />
<Using Include="System.DateTime" Alias="DT" />
</ItemGroup> <ItemGroup>
<Using Include="System.DateTime" Alias="DT" />
</ItemGroup><ItemGroup Condition="'$(TargetFramework)' == 'net472'">
<Project> <ItemGroup Label="Exceptions"> <Using Include="Ces.Caspian.Constants.Constants.Application.MapTargets" Alias="conMapTargets" /> </ItemGroup> <ItemGroup Label="OperationResult"> <Using Include="Ces.Caspian.Models.OperationResult" Alias="oResult" /> </ItemGroup> <ItemGroup Label="Constants"> <!-- Application --> <Using Include="Ces.Caspian.Constants.Constants.Application.MapTargets" Alias="conMapTargets" /> <Using Include="Ces.Caspian.Constants.Constants.Application.Profiles" Alias="conProfiles" /> <Using Include="Ces.Caspian.Constants.Constants.Application.Settings" Alias="conSettings" /> <!-- Piping --> <Using Include="Ces.Caspian.Constants.Constants.Piping.AGUGs" Alias="conAGUGs" /> <Using Include="Ces.Caspian.Constants.Constants.Piping.ConnectionTypes" Alias="conConnectionTypes" /> <Using Include="Ces.Caspian.Constants.Constants.Piping.EndStatuses" Alias="conEndStatuses" /> <Using Include="Ces.Caspian.Constants.Constants.Piping.EndTypes" Alias="conEndTypes" /> <!-- Project --> <Using Include="Ces.Caspian.Constants.Constants.Project.Disciplines" Alias="conDisciplines" /> <!-- TestPackage --> <Using Include="Ces.Caspian.Constants.Constants.TestPackage.TestPackageActions" Alias="conTestPackageActions" /> <Using Include="Ces.Caspian.Constants.Constants.TestPackage.TestPackageActivities" Alias="conTestPackageActivities" /> </ItemGroup> </Project>
// <auto-generated/> global using global::System; global using global::System.Collections.Generic; global using global::System.IO; global using global::System.Linq; global using global::System.Net.Http; global using global::System.Threading; global using global::System.Threading.Tasks; global using acActionMethods = global::Ces.Caspian.Application.Handlers.Application.ActionMethods.Commands; //خطا global using acActivities = global::Ces.Caspian.Application.Handlers.TestPackage.Activities.Commands; //خطا global using acAfterTests = global::Ces.Caspian.Application.Handlers.Piping.AfterTests.Commands; //خطا global using acAGUGs = global::Ces.Caspian.Application.Handlers.Piping.AGUGs.Commands; //خطا global using acAreas = global::Ces.Caspian.Application.Handlers.Project.Areas.Commands; //خطا
Directory.Build.props به تمام پروژهها اعمال میشود. وقتی شما یک Using سراسری برای یک فضاینام (namespace) خاص تعریف میکنید، کامپایلر تلاش میکند آن را در همهی پروژهها اعمال کند. اگر پروژهای (مانند پروژه Abstraction شما) ارجاعی (ProjectReference) به اسمبلی حاوی آن فضاینام نداشته باشد، با خطای "The type or namespace name ... could not be found" مواجه میشوید. این رفتار کاملاً طبیعی است. راه حل این است که ItemGroup های حاوی دستورات Using را مشروط کنید. Ces.Caspian.Application.* در پروژه Ces.Caspian.Application.csprojCes.Caspian.Constants.* در پروژه Ces.Caspian.Constants.csprojCes.Caspian.Models.* در پروژه Ces.Caspian.Models.csprojDirectory.Build.props شما میتواند به شکل زیر بازنویسی شود:<Project>
<ItemGroup Condition="'@(ProjectReference->WithMetadataValue('Filename', 'Ces.Caspian.Constants')->Count())' > '0'">
<Using Include="Ces.Caspian.Constants.Constants.Application.MapTargets" Alias="conMapTargets" />
<Using Include="Ces.Caspian.Constants.Constants.Application.Profiles" Alias="conProfiles" />
<Using Include="Ces.Caspian.Constants.Constants.Application.Settings" Alias="conSettings" />
<Using Include="Ces.Caspian.Constants.Constants.Piping.AGUGs" Alias="conAGUGs" />
<Using Include="Ces.Caspian.Constants.Constants.Piping.ConnectionTypes" Alias="conConnectionTypes" />
<Using Include="Ces.Caspian.Constants.Constants.Piping.EndStatuses" Alias="conEndStatuses" />
<Using Include="Ces.Caspian.Constants.Constants.Piping.EndTypes" Alias="conEndTypes" />
<Using Include="Ces.Caspian.Constants.Constants.Project.Disciplines" Alias="conDisciplines" />
<Using Include="Ces.Caspian.Constants.Constants.TestPackage.TestPackageActions" Alias="conTestPackageActions" />
<Using Include="Ces.Caspian.Constants.Constants.TestPackage.TestPackageActivities" Alias="conTestPackageActivities" />
</ItemGroup>
<ItemGroup Condition="'@(ProjectReference->WithMetadataValue('Filename', 'Ces.Caspian.Models')->Count())' > '0'">
<Using Include="Ces.Caspian.Models.OperationResult" Alias="oResult" />
</ItemGroup>
<ItemGroup Condition="'@(ProjectReference->WithMetadataValue('Filename', 'Ces.Caspian.Application')->Count())' > '0'">
<Using Include="Ces.Caspian.Application.Handlers.Application.ActionMethods.Commands" Alias="acActionMethods" />
<Using Include="Ces.Caspian.Application.Handlers.TestPackage.Activities.Commands" Alias="acActivities" />
<Using Include="Ces.Caspian.Application.Handlers.Piping.AfterTests.Commands" Alias="acAfterTests" />
<Using Include="Ces.Caspian.Application.Handlers.Piping.AGUGs.Commands" Alias="acAGUGs" />
<Using Include="Ces.Caspian.Application.Handlers.Project.Areas.Commands" Alias="acAreas" />
</ItemGroup>
</Project>Condition="...": این یک ویژگی استاندارد در MSBuild است که به شما اجازه میدهد یک ItemGroup (یا هر عنصر دیگری) را فقط در صورت برقراری یک شرط خاص، پردازش کنید.'@(ProjectReference...)': این دستور لیست تمام ارجاعات پروژه را در فایل .csproj پروژه فعلی انتخاب میکند.->WithMetadataValue('Filename', 'Ces.Caspian.Constants'): این بخش، لیست ProjectReference ها را فیلتر میکند و فقط آنهایی را نگه میدارد که نام فایلشان (بدون پسوند) برابر با Ces.Caspian.Constants باشد.->Count(): تعداد آیتمهای باقیمانده در لیست فیلتر شده را میشمارد.> '0': شرط نهایی بررسی میکند که آیا تعداد ارجاعات پیدا شده بزرگتر از صفر است یا خیر. اگر چنین باشد، شرط برقرار است و ItemGroup مربوطه به پروژه اضافه میشود.Using های سراسری مربوط به وابستگیهای خودش را دریافت میکند و مشکل بیلد در پروژههایی مانند Abstraction که وابستگیهای کمتری دارند، به طور کامل حل میشود. در ضمن، قابلیت استفاده از Alias همچنان پابرجاست و مشکلی از این بابت وجود ندارد.OR , AND برای افزودن پارامتر به condition و عملگر != برای بررسی استفاده کرد. همچنین استفاده از condition در تگهای Include هم امکانپذیر است:<ItemGroup Label="Constants" Condition=" '$(MSBuildProjectName)' == 'Ces.Caspian.Api' OR '$(MSBuildProjectName)' == 'Ces.Caspian.Infrastructure' OR '$(MSBuildProjectName)' == 'Ces.Caspian.Domain' OR '$(MSBuildProjectName)' == 'Ces.Caspian.Models' OR '$(MSBuildProjectName)' == 'Ces.Caspian.WinClient' ">
public static string CurrentInvariantMonthName()
{
var month = DateTimeOffset.UtcNow.Month;
return CultureInfo
.InvariantCulture
.DateTimeFormat
.GetMonthName(month);
} #if MOCK_TIME
global using DateTimeOffset = StubDateTimeOffset;
#else
global using DateTimeOffset = System.DateTimeOffset;
#endif
public static class StubDateTimeOffset
{
private static System.DateTimeOffset? value;
public static System.DateTimeOffset UtcNow
=> value ?? System.DateTimeOffset.UtcNow ;
public static void Set(System.DateTimeOffset dateTimeOffset) {
value = dateTimeOffset;
}
public static void Reset() => value = null;
} <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> <DefineConstants>MOCK_TIME</DefineConstants> </PropertyGroup>
// set time StubDateTimeOffset.Set(new(new(2022, 7, 1)));