<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      C# - 獲取枚舉描述 - 使用增量源生成器

      前言

      C# 獲取枚舉描述的方法有很多, 常用的有通過 DescriptionAttribute 反射獲取, 進階的可以加上緩存機制, 減少反射的開銷。今天我們還提供一種更加高效的方法,通過增量源生成器生成獲取枚舉描述的代碼。這是在編譯層面實現的, 無需反射, 性能更高。

      本文的演示代碼基于 VS2022 + .NET 8.0 + .NET Standard 2.0

      1. 基本反射

      這種方法是最常用的方法, 但是反射開銷比較大。

      public enum Color
      {
          [Description("紅色")]
          Red,
          [Description("綠色")]
          Green,
          [Description("藍色")]
          Blue
      }
      
      public static string GetDescription(Color color)
      {
          var fieldInfo = typeof(Color).GetField(color.ToString());
          var descriptionAttribute = fieldInfo.GetCustomAttribute<DescriptionAttribute>();
          return descriptionAttribute?.Description;
      }
      

      2. 反射 + 緩存

      緩存機制可以減少反射的開銷, 避免反射過于頻繁。

      private static readonly Dictionary<Color, string> _descriptionCache = new Dictionary<Color, string>();
      
      public static string GetDescription(Color color)
      {
          if (_descriptionCache.TryGetValue(color, out var description))
          {
              return description;
          }
      
          var fieldInfo = typeof(Color).GetField(color.ToString());
          var descriptionAttribute = fieldInfo.GetCustomAttribute<DescriptionAttribute>();
          description = descriptionAttribute?.Description;
          _descriptionCache.Add(color, description);
          return description;
      }
      

      3. 反射 + 緩存 + 泛型類 (推薦)

      泛型可以減少代碼重復。下面的代碼為基本實現, 沒有考慮線程安全問題。線程安全問題可以通過鎖機制解決。可以使用靜態構造函數初始化緩存。或者使用 ConcurrentDictionary 代替 Dictionary。或者使用 Lazy 代替緩存。

      public class EnumDescription<T> where T : Enum
      {
          private static readonly Dictionary<T, string> _descriptionCache = new Dictionary<T, string>();
      
          public static string GetDescription(T value)
          {
              if (_descriptionCache.TryGetValue(value, out var description))
              {
                  return description;
              }
      
              var fieldInfo = typeof(T).GetField(value.ToString());
              var descriptionAttribute = fieldInfo.GetCustomAttribute<DescriptionAttribute>();
              description = descriptionAttribute?.Description;
              _descriptionCache.Add(value, description);
              return description;
          }
      }
      

      4. 增量源生成器 (消除反射)

      創建增量源生成器類庫項目 (.NET Standard 2.0)

      1. 創建一個基于 .NET Standard 2.0 的類庫項目名為: SourceGenerator

      2. 添加 NuGet 包 Microsoft.CodeAnalysis.CSharp 版本 4.8.0

      <Project Sdk="Microsoft.NET.Sdk">
      	<PropertyGroup>
      		<TargetFramework>netstandard2.0</TargetFramework>
      		<LangVersion>latest</LangVersion>
      		<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
      	</PropertyGroup>
      
      	<ItemGroup>
      		<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.8.0" />
      	</ItemGroup>
      </Project>
      
      1. 添加 EnumDescriptionGenerator 類, 實現 IIncrementalGenerator 接口
      using System.Linq;
      using System.Text;
      using Microsoft.CodeAnalysis;
      using Microsoft.CodeAnalysis.CSharp.Syntax;
      using Microsoft.CodeAnalysis.Text;
      
      
      [Generator]
      public class EnumDescriptionGenerator : IIncrementalGenerator
      {
          public void Initialize(IncrementalGeneratorInitializationContext context)
          {
              var enumDeclarations = context.SyntaxProvider
                 .CreateSyntaxProvider(
                      predicate: (syntaxNode, _) => syntaxNode is EnumDeclarationSyntax,
                      transform: (generatorSyntaxContext, _) =>
                      {
                          var enumDeclaration = (EnumDeclarationSyntax)generatorSyntaxContext.Node;
                          var enumSymbol = generatorSyntaxContext.SemanticModel.GetDeclaredSymbol(enumDeclaration) as INamedTypeSymbol;
                          return new { EnumDeclaration = enumDeclaration, EnumSymbol = enumSymbol };
                      })
                 .Where(t => t.EnumSymbol != null)
                 .Collect();
      
              var compilationAndEnums = context.CompilationProvider.Combine(enumDeclarations);
      
              context.RegisterSourceOutput(compilationAndEnums, (sourceProductionContext, tuple) =>
              {
                  var compilation = tuple.Left;
                  var enums = tuple.Right;
      
                  foreach (var item in enums)
                  {
                      var enumDeclaration = item.EnumDeclaration;
                      var enumSymbol = item.EnumSymbol;
      
                      if (!enumSymbol.GetMembers("GetDescription").Any())
                      {
                          var source = GenerateSourceCode(enumSymbol);
                          sourceProductionContext.AddSource($"{enumSymbol.Name}Descriptions.g.cs", SourceText.From(source, Encoding.UTF8));
                      }
                  }
      
              });
          }
      
      
          // 生成枚舉描述擴展方法的代碼
          private static string GenerateSourceCode(INamedTypeSymbol enumSymbol)
          {
              var enumName = enumSymbol.Name;
              var namespaceName = enumSymbol.ContainingNamespace?.ToString() ?? "Global";
      
              var sb = new StringBuilder();
              sb.AppendLine($"namespace {namespaceName};");
              sb.AppendLine($"public static partial class {enumName}Extensions");
              sb.AppendLine("{");
              sb.AppendLine($"    public static string GetDescription(this {enumName} value) =>");
              sb.AppendLine("        value switch");
              sb.AppendLine("        {");
      
              // 4. 遍歷枚舉成員
              foreach (var member in enumSymbol.GetMembers().Where(m => m.Kind == SymbolKind.Field))
              {
                  var description = member.GetAttributes()
                      .FirstOrDefault(a => a.AttributeClass?.Name == "DescriptionAttribute")
                      ?.ConstructorArguments.FirstOrDefault().Value?.ToString()
                      ?? member.Name;
      
                  sb.AppendLine($"            {enumName}.{member.Name} => \"{description}\",");
              }
      
              sb.AppendLine("            _ => string.Empty");
              sb.AppendLine("        };");
              sb.AppendLine("}");
              return sb.ToString();
          }
      }
      
      

      創建控制臺主項目 MainProject

      1. 使用 .NET 8.0 , 引用 SourceGenerator 項目, 注意引用方式如下:
      <Project Sdk="Microsoft.NET.Sdk">
      
      	<PropertyGroup>
      		<OutputType>Exe</OutputType>
      		<TargetFramework>net8.0</TargetFramework>
      		<ImplicitUsings>enable</ImplicitUsings>
      		<Nullable>enable</Nullable>
      	</PropertyGroup>
      
      	<ItemGroup>
      		<ProjectReference Include="..\SourceGenerator\SourceGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
      	</ItemGroup>
      
      </Project>
      
      
      1. MainProject 中使用生成的枚舉描述擴展方法
      namespace MainProject;
      
      class Program
      {
          static void Main()
          {
              foreach (var color in Enum.GetValues<Color>())
              {
                  Console.WriteLine(color.GetDescription());
              }
              Console.ReadKey();
          }
      }
      
      1. 編譯運行, 編譯器會自動生成枚舉描述擴展方法的代碼。

      演示程序截圖:

      image

      image

      總結

      通過增量源生成器, 我們可以在編譯期自動生成獲取枚舉描述的代碼, 無需反射, 性能更高。

      posted @ 2025-03-24 14:26  Broadm  閱讀(907)  評論(2)    收藏  舉報
      主站蜘蛛池模板: 日本一区二区三区在线看| 4虎四虎永久在线精品免费| 欧美白人最猛性xxxxx| 国产精品午夜福利91| mm1313亚洲国产精品| 成人午夜在线播放| 亚洲精品有码在线观看| 国产精品国产自产拍高清| 精品人妻无码一区二区三区性| 日韩大片看一区二区三区| 中文字幕av无码免费一区| 亚洲人成电影网站色mp4| 亚洲欧美综合精品成| 免费A级毛片无码A∨蜜芽试看| 欧美日韩一线| 亚洲日韩精品无码av海量| 精品国产免费一区二区三区香蕉| 亚洲av午夜福利精品一区二区| 一区二区三区四区精品视频| 99在线精品视频观看免费| 人妻中文字幕精品系列| 灵璧县| 天天躁日日躁狠狠躁中文字幕| 色伦专区97中文字幕| 九九热免费在线视频观看| 久久不见久久见免费视频观看| 国产一区二区三区av在线无码观看 | 色二av手机版在线| 亚洲国产精品综合一区二区 | 中文在线最新版天堂| 日日麻批免费40分钟无码| 久青草国产在视频在线观看| 日日碰狠狠添天天爽五月婷| 午夜福利宅福利国产精品| 国语精品一区二区三区| 色综合久久天天综线观看| av日韩精品在线播放| 国产精品普通话国语对白露脸| 人妻精品中文字幕av| 亚洲中文字幕国产综合| 无码国内精品人妻少妇|