翼度科技»论坛 编程开发 .net 查看内容

Fireasy3 揭秘 -- 使用 SourceGeneraor 改进服务发现

4

主题

4

帖子

12

积分

新手上路

Rank: 1

积分
12
目录

  在 Fireasy3 揭秘 -- 依赖注入与服务发现 这篇中,我们通过遍列程序集中的所有类,来查找三个类型的服务接口,这样应用在启动时会消耗一定的时间来处理这些事情。今天,我们将用 ISourceGenerator 来对它进行改进。
  ISourceGenerator 是 Microsoft.CodeAnalysis.Analyzers 中的一项技术,它是基于代码分析的原理,在语法树中查找所需要的内容,通过这些内容再构造一段源代码,使得我们在编译程序集的时候,把这些代码一并编译进去。使用它的好处在于,它是在编译时生成的,而不像 Emit 或其他反射等方法来构建的动态代码一样,在运行时将耗费一定的性能。
  需要新建一个 .net standard 2.0 的项目,并引入 Microsoft.CodeAnalysis.Analyzers 和 Microsoft.CodeAnalysis.CSharp,见 Fireasy.Common.Analyzers
  在项目里添加一个类,实现 ISourceGenerator 接口,如下:
  1.     [Generator]
  2.     public class ServiceDiscoverGenerator : ISourceGenerator
  3.     {
  4. <Project Sdk="Microsoft.NET.Sdk">
  5.   <ItemGroup>
  6.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  7.   </ItemGroup>
  8. </Project>void ISourceGenerator.Initialize(GeneratorInitializationContext context)
  9. <Project Sdk="Microsoft.NET.Sdk">
  10.   <ItemGroup>
  11.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  12.   </ItemGroup>
  13. </Project>{
  14. <Project Sdk="Microsoft.NET.Sdk">
  15.   <ItemGroup>
  16.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  17.   </ItemGroup>
  18. </Project>    Debugger.Launch();
  19. <Project Sdk="Microsoft.NET.Sdk">
  20.   <ItemGroup>
  21.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  22.   </ItemGroup>
  23. </Project>    context.RegisterForSyntaxNotifications(() => new ServiceDiscoverSyntaxReceiver());
  24. <Project Sdk="Microsoft.NET.Sdk">
  25.   <ItemGroup>
  26.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  27.   </ItemGroup>
  28. </Project>}
  29. <Project Sdk="Microsoft.NET.Sdk">
  30.   <ItemGroup>
  31.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  32.   </ItemGroup>
  33. </Project>void ISourceGenerator.Execute(GeneratorExecutionContext context)
  34. <Project Sdk="Microsoft.NET.Sdk">
  35.   <ItemGroup>
  36.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  37.   </ItemGroup>
  38. </Project>{
  39. <Project Sdk="Microsoft.NET.Sdk">
  40.   <ItemGroup>
  41.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  42.   </ItemGroup>
  43. </Project>}
  44.     }
复制代码
  Initialize 方法用于初始化生成器,使用 RegisterForSyntaxNotifications 方法向上下文注入一个语法接收器,以便用来分析语法树。这里的语法接收器有两种,分别是 ISyntaxReceiver 和 ISyntaxContextReceiver,后者可以从上下文中获取到 SemanticModel 对象,这样的话能够从语法节点中获取到定义的符号模型。使用符号模型相对于语法节点来说要更方便一些。下面是基于 ISyntaxContextReceiver 接口的语法接收器。
  1.     internal class ServiceDiscoverSyntaxReceiver : ISyntaxContextReceiver
  2.     {
  3. <Project Sdk="Microsoft.NET.Sdk">
  4.   <ItemGroup>
  5.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  6.   </ItemGroup>
  7. </Project>private const string SingletonServiceName = "Fireasy.Common.DependencyInjection.ISingletonService";
  8. <Project Sdk="Microsoft.NET.Sdk">
  9.   <ItemGroup>
  10.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  11.   </ItemGroup>
  12. </Project>private const string TransientServiceName = "Fireasy.Common.DependencyInjection.ITransientService";
  13. <Project Sdk="Microsoft.NET.Sdk">
  14.   <ItemGroup>
  15.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  16.   </ItemGroup>
  17. </Project>private const string ScopedServiceName = "Fireasy.Common.DependencyInjection.IScopedService";
  18. <Project Sdk="Microsoft.NET.Sdk">
  19.   <ItemGroup>
  20.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  21.   </ItemGroup>
  22. </Project>private const string RegisterAttributeName = "Fireasy.Common.DependencyInjection.ServiceRegisterAttribute";
  23. <Project Sdk="Microsoft.NET.Sdk">
  24.   <ItemGroup>
  25.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  26.   </ItemGroup>
  27. </Project>private List<ClassMetadata> _metadatas = new();
  28. <Project Sdk="Microsoft.NET.Sdk">
  29.   <ItemGroup>
  30.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  31.   </ItemGroup>
  32. </Project>void ISyntaxContextReceiver.OnVisitSyntaxNode(GeneratorSyntaxContext context)
  33. <Project Sdk="Microsoft.NET.Sdk">
  34.   <ItemGroup>
  35.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  36.   </ItemGroup>
  37. </Project>{
  38. <Project Sdk="Microsoft.NET.Sdk">
  39.   <ItemGroup>
  40.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  41.   </ItemGroup>
  42. </Project>    if (context.Node is ClassDeclarationSyntax classSyntax)
  43. <Project Sdk="Microsoft.NET.Sdk">
  44.   <ItemGroup>
  45.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  46.   </ItemGroup>
  47. </Project>    {
  48. <Project Sdk="Microsoft.NET.Sdk">
  49.   <ItemGroup>
  50.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  51.   </ItemGroup>
  52. </Project><Project Sdk="Microsoft.NET.Sdk">
  53.   <ItemGroup>
  54.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  55.   </ItemGroup>
  56. </Project>AnalyseClassSyntax(context.SemanticModel, classSyntax);
  57. <Project Sdk="Microsoft.NET.Sdk">
  58.   <ItemGroup>
  59.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  60.   </ItemGroup>
  61. </Project>    }
  62. <Project Sdk="Microsoft.NET.Sdk">
  63.   <ItemGroup>
  64.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  65.   </ItemGroup>
  66. </Project>}
  67.     }
复制代码
  OnVisitSyntaxNode 方法正如 lambda 表达式树的 ExpressionVisitor 一样,语法树中的每一个节点都会被它访问到。我们需要分析的是类,因此只需要处理 ClassDeclarationSyntax 语法即可。AnalyseClassSyntax 方法如下:
  1. <Project Sdk="Microsoft.NET.Sdk">
  2.   <ItemGroup>
  3.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  4.   </ItemGroup>
  5. </Project>/// <summary>
  6. <Project Sdk="Microsoft.NET.Sdk">
  7.   <ItemGroup>
  8.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  9.   </ItemGroup>
  10. </Project>/// 分析类型语法。
  11. <Project Sdk="Microsoft.NET.Sdk">
  12.   <ItemGroup>
  13.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  14.   </ItemGroup>
  15. </Project>/// </summary>
  16. <Project Sdk="Microsoft.NET.Sdk">
  17.   <ItemGroup>
  18.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  19.   </ItemGroup>
  20. </Project>/// <param name="model"></param>
  21. <Project Sdk="Microsoft.NET.Sdk">
  22.   <ItemGroup>
  23.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  24.   </ItemGroup>
  25. </Project>/// <param name="syntax"></param>
  26. <Project Sdk="Microsoft.NET.Sdk">
  27.   <ItemGroup>
  28.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  29.   </ItemGroup>
  30. </Project>private void AnalyseClassSyntax(SemanticModel model, ClassDeclarationSyntax syntax)
  31. <Project Sdk="Microsoft.NET.Sdk">
  32.   <ItemGroup>
  33.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  34.   </ItemGroup>
  35. </Project>{
  36. <Project Sdk="Microsoft.NET.Sdk">
  37.   <ItemGroup>
  38.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  39.   </ItemGroup>
  40. </Project>    var typeSymbol = (ITypeSymbol)model.GetDeclaredSymbol(syntax)!;
  41. <Project Sdk="Microsoft.NET.Sdk">
  42.   <ItemGroup>
  43.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  44.   </ItemGroup>
  45. </Project>    var interfaces = typeSymbol.Interfaces;
  46. <Project Sdk="Microsoft.NET.Sdk">
  47.   <ItemGroup>
  48.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  49.   </ItemGroup>
  50. </Project>    //判断是否使用了 特殊
  51. <Project Sdk="Microsoft.NET.Sdk">
  52.   <ItemGroup>
  53.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  54.   </ItemGroup>
  55. </Project>    var regAttr = typeSymbol.GetAttributes().FirstOrDefault(s => s.AttributeClass!.ToDisplayString() == RegisterAttributeName);
  56. <Project Sdk="Microsoft.NET.Sdk">
  57.   <ItemGroup>
  58.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  59.   </ItemGroup>
  60. </Project>    var lifetime = string.Empty;
  61. <Project Sdk="Microsoft.NET.Sdk">
  62.   <ItemGroup>
  63.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  64.   </ItemGroup>
  65. </Project>    if (regAttr != null)
  66. <Project Sdk="Microsoft.NET.Sdk">
  67.   <ItemGroup>
  68.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  69.   </ItemGroup>
  70. </Project>    {
  71. <Project Sdk="Microsoft.NET.Sdk">
  72.   <ItemGroup>
  73.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  74.   </ItemGroup>
  75. </Project><Project Sdk="Microsoft.NET.Sdk">
  76.   <ItemGroup>
  77.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  78.   </ItemGroup>
  79. </Project>lifetime = GetLifetime((int)regAttr.ConstructorArguments[0].Value!);
  80. <Project Sdk="Microsoft.NET.Sdk">
  81.   <ItemGroup>
  82.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  83.   </ItemGroup>
  84. </Project>    }
  85. <Project Sdk="Microsoft.NET.Sdk">
  86.   <ItemGroup>
  87.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  88.   </ItemGroup>
  89. </Project>    else if (interfaces.Any(s => s.ToDisplayString() == SingletonServiceName))
  90. <Project Sdk="Microsoft.NET.Sdk">
  91.   <ItemGroup>
  92.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  93.   </ItemGroup>
  94. </Project>    {
  95. <Project Sdk="Microsoft.NET.Sdk">
  96.   <ItemGroup>
  97.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  98.   </ItemGroup>
  99. </Project><Project Sdk="Microsoft.NET.Sdk">
  100.   <ItemGroup>
  101.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  102.   </ItemGroup>
  103. </Project>lifetime = "Singleton";
  104. <Project Sdk="Microsoft.NET.Sdk">
  105.   <ItemGroup>
  106.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  107.   </ItemGroup>
  108. </Project>    }
  109. <Project Sdk="Microsoft.NET.Sdk">
  110.   <ItemGroup>
  111.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  112.   </ItemGroup>
  113. </Project>    else if (interfaces.Any(s => s.ToDisplayString() == TransientServiceName))
  114. <Project Sdk="Microsoft.NET.Sdk">
  115.   <ItemGroup>
  116.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  117.   </ItemGroup>
  118. </Project>    {
  119. <Project Sdk="Microsoft.NET.Sdk">
  120.   <ItemGroup>
  121.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  122.   </ItemGroup>
  123. </Project><Project Sdk="Microsoft.NET.Sdk">
  124.   <ItemGroup>
  125.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  126.   </ItemGroup>
  127. </Project>lifetime = "Transient";
  128. <Project Sdk="Microsoft.NET.Sdk">
  129.   <ItemGroup>
  130.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  131.   </ItemGroup>
  132. </Project>    }
  133. <Project Sdk="Microsoft.NET.Sdk">
  134.   <ItemGroup>
  135.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  136.   </ItemGroup>
  137. </Project>    else if (interfaces.Any(s => s.ToDisplayString() == ScopedServiceName))
  138. <Project Sdk="Microsoft.NET.Sdk">
  139.   <ItemGroup>
  140.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  141.   </ItemGroup>
  142. </Project>    {
  143. <Project Sdk="Microsoft.NET.Sdk">
  144.   <ItemGroup>
  145.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  146.   </ItemGroup>
  147. </Project><Project Sdk="Microsoft.NET.Sdk">
  148.   <ItemGroup>
  149.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  150.   </ItemGroup>
  151. </Project>lifetime = "Scoped";
  152. <Project Sdk="Microsoft.NET.Sdk">
  153.   <ItemGroup>
  154.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  155.   </ItemGroup>
  156. </Project>    }
  157. <Project Sdk="Microsoft.NET.Sdk">
  158.   <ItemGroup>
  159.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  160.   </ItemGroup>
  161. </Project>    if (!string.IsNullOrEmpty(lifetime))
  162. <Project Sdk="Microsoft.NET.Sdk">
  163.   <ItemGroup>
  164.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  165.   </ItemGroup>
  166. </Project>    {
  167. <Project Sdk="Microsoft.NET.Sdk">
  168.   <ItemGroup>
  169.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  170.   </ItemGroup>
  171. </Project><Project Sdk="Microsoft.NET.Sdk">
  172.   <ItemGroup>
  173.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  174.   </ItemGroup>
  175. </Project>var serviceTypes = GetServiceTypes(interfaces).ToList();
  176. <Project Sdk="Microsoft.NET.Sdk">
  177.   <ItemGroup>
  178.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  179.   </ItemGroup>
  180. </Project><Project Sdk="Microsoft.NET.Sdk">
  181.   <ItemGroup>
  182.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  183.   </ItemGroup>
  184. </Project>//如果没有实现任何接口,则判断基类是不是抽象类,如果不是,则注册自己
  185. <Project Sdk="Microsoft.NET.Sdk">
  186.   <ItemGroup>
  187.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  188.   </ItemGroup>
  189. </Project><Project Sdk="Microsoft.NET.Sdk">
  190.   <ItemGroup>
  191.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  192.   </ItemGroup>
  193. </Project>if (serviceTypes.Count == 0 && (typeSymbol.BaseType?.Name == "Object" || typeSymbol.BaseType?.IsAbstract == false))
  194. <Project Sdk="Microsoft.NET.Sdk">
  195.   <ItemGroup>
  196.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  197.   </ItemGroup>
  198. </Project><Project Sdk="Microsoft.NET.Sdk">
  199.   <ItemGroup>
  200.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  201.   </ItemGroup>
  202. </Project>{
  203. <Project Sdk="Microsoft.NET.Sdk">
  204.   <Target Name="_IncludeAllDependencies" BeforeTargets="_GetPackageFiles">
  205.     <ItemGroup>
  206. <Project Sdk="Microsoft.NET.Sdk">
  207.   <ItemGroup>
  208.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  209.   </ItemGroup>
  210. </Project><None Include="..\Fireasy.Common.Analyzers\bin\$(Configuration)\**\*.dll" Pack="True" PackagePath="analyzers\dotnet\cs" />
  211.     </ItemGroup>
  212.   </Target>
  213. </Project>serviceTypes.Add(typeSymbol);
  214. <Project Sdk="Microsoft.NET.Sdk">
  215.   <ItemGroup>
  216.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  217.   </ItemGroup>
  218. </Project><Project Sdk="Microsoft.NET.Sdk">
  219.   <ItemGroup>
  220.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  221.   </ItemGroup>
  222. </Project>}
  223. <Project Sdk="Microsoft.NET.Sdk">
  224.   <ItemGroup>
  225.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  226.   </ItemGroup>
  227. </Project><Project Sdk="Microsoft.NET.Sdk">
  228.   <ItemGroup>
  229.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  230.   </ItemGroup>
  231. </Project>_metadatas.Add(new ClassMetadata(typeSymbol, lifetime).AddServiceTypes(serviceTypes));
  232. <Project Sdk="Microsoft.NET.Sdk">
  233.   <ItemGroup>
  234.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  235.   </ItemGroup>
  236. </Project>    }
  237. <Project Sdk="Microsoft.NET.Sdk">
  238.   <ItemGroup>
  239.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  240.   </ItemGroup>
  241. </Project>}
  242. <Project Sdk="Microsoft.NET.Sdk">
  243.   <ItemGroup>
  244.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  245.   </ItemGroup>
  246. </Project>/// <summary>
  247. <Project Sdk="Microsoft.NET.Sdk">
  248.   <ItemGroup>
  249.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  250.   </ItemGroup>
  251. </Project>/// 获取生命周期。
  252. <Project Sdk="Microsoft.NET.Sdk">
  253.   <ItemGroup>
  254.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  255.   </ItemGroup>
  256. </Project>/// </summary>
  257. <Project Sdk="Microsoft.NET.Sdk">
  258.   <ItemGroup>
  259.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  260.   </ItemGroup>
  261. </Project>/// <param name="value"></param>
  262. <Project Sdk="Microsoft.NET.Sdk">
  263.   <ItemGroup>
  264.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  265.   </ItemGroup>
  266. </Project>/// <returns></returns>
  267. <Project Sdk="Microsoft.NET.Sdk">
  268.   <ItemGroup>
  269.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  270.   </ItemGroup>
  271. </Project>private string GetLifetime(int value) => value switch
  272. <Project Sdk="Microsoft.NET.Sdk">
  273.   <ItemGroup>
  274.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  275.   </ItemGroup>
  276. </Project>{
  277. <Project Sdk="Microsoft.NET.Sdk">
  278.   <ItemGroup>
  279.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  280.   </ItemGroup>
  281. </Project>    0 => "Singleton",
  282. <Project Sdk="Microsoft.NET.Sdk">
  283.   <ItemGroup>
  284.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  285.   </ItemGroup>
  286. </Project>    1 => "Scoped",
  287. <Project Sdk="Microsoft.NET.Sdk">
  288.   <ItemGroup>
  289.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  290.   </ItemGroup>
  291. </Project>    2 => "Transient",
  292. <Project Sdk="Microsoft.NET.Sdk">
  293.   <ItemGroup>
  294.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  295.   </ItemGroup>
  296. </Project>    _ => string.Empty
  297. <Project Sdk="Microsoft.NET.Sdk">
  298.   <ItemGroup>
  299.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  300.   </ItemGroup>
  301. </Project>};
  302. <Project Sdk="Microsoft.NET.Sdk">
  303.   <ItemGroup>
  304.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  305.   </ItemGroup>
  306. </Project>/// <summary>
  307. <Project Sdk="Microsoft.NET.Sdk">
  308.   <ItemGroup>
  309.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  310.   </ItemGroup>
  311. </Project>/// 从接口中筛选出服务类。
  312. <Project Sdk="Microsoft.NET.Sdk">
  313.   <ItemGroup>
  314.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  315.   </ItemGroup>
  316. </Project>/// </summary>
  317. <Project Sdk="Microsoft.NET.Sdk">
  318.   <ItemGroup>
  319.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  320.   </ItemGroup>
  321. </Project>/// <param name="types"></param>
  322. <Project Sdk="Microsoft.NET.Sdk">
  323.   <ItemGroup>
  324.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  325.   </ItemGroup>
  326. </Project>/// <returns></returns>
  327. <Project Sdk="Microsoft.NET.Sdk">
  328.   <ItemGroup>
  329.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  330.   </ItemGroup>
  331. </Project>private IEnumerable<ITypeSymbol> GetServiceTypes(IEnumerable<INamedTypeSymbol> types)
  332. <Project Sdk="Microsoft.NET.Sdk">
  333.   <ItemGroup>
  334.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  335.   </ItemGroup>
  336. </Project>{
  337. <Project Sdk="Microsoft.NET.Sdk">
  338.   <ItemGroup>
  339.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  340.   </ItemGroup>
  341. </Project>    foreach (var type in types)
  342. <Project Sdk="Microsoft.NET.Sdk">
  343.   <ItemGroup>
  344.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  345.   </ItemGroup>
  346. </Project>    {
  347. <Project Sdk="Microsoft.NET.Sdk">
  348.   <ItemGroup>
  349.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  350.   </ItemGroup>
  351. </Project><Project Sdk="Microsoft.NET.Sdk">
  352.   <ItemGroup>
  353.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  354.   </ItemGroup>
  355. </Project>if (type.ToDisplayString() == SingletonServiceName ||
  356. <Project Sdk="Microsoft.NET.Sdk">
  357.   <Target Name="_IncludeAllDependencies" BeforeTargets="_GetPackageFiles">
  358.     <ItemGroup>
  359. <Project Sdk="Microsoft.NET.Sdk">
  360.   <ItemGroup>
  361.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  362.   </ItemGroup>
  363. </Project><None Include="..\Fireasy.Common.Analyzers\bin\$(Configuration)\**\*.dll" Pack="True" PackagePath="analyzers\dotnet\cs" />
  364.     </ItemGroup>
  365.   </Target>
  366. </Project>type.ToDisplayString() == TransientServiceName ||
  367. <Project Sdk="Microsoft.NET.Sdk">
  368.   <Target Name="_IncludeAllDependencies" BeforeTargets="_GetPackageFiles">
  369.     <ItemGroup>
  370. <Project Sdk="Microsoft.NET.Sdk">
  371.   <ItemGroup>
  372.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  373.   </ItemGroup>
  374. </Project><None Include="..\Fireasy.Common.Analyzers\bin\$(Configuration)\**\*.dll" Pack="True" PackagePath="analyzers\dotnet\cs" />
  375.     </ItemGroup>
  376.   </Target>
  377. </Project>type.ToDisplayString() == ScopedServiceName)
  378. <Project Sdk="Microsoft.NET.Sdk">
  379.   <ItemGroup>
  380.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  381.   </ItemGroup>
  382. </Project><Project Sdk="Microsoft.NET.Sdk">
  383.   <ItemGroup>
  384.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  385.   </ItemGroup>
  386. </Project>{
  387. <Project Sdk="Microsoft.NET.Sdk">
  388.   <Target Name="_IncludeAllDependencies" BeforeTargets="_GetPackageFiles">
  389.     <ItemGroup>
  390. <Project Sdk="Microsoft.NET.Sdk">
  391.   <ItemGroup>
  392.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  393.   </ItemGroup>
  394. </Project><None Include="..\Fireasy.Common.Analyzers\bin\$(Configuration)\**\*.dll" Pack="True" PackagePath="analyzers\dotnet\cs" />
  395.     </ItemGroup>
  396.   </Target>
  397. </Project>continue;
  398. <Project Sdk="Microsoft.NET.Sdk">
  399.   <ItemGroup>
  400.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  401.   </ItemGroup>
  402. </Project><Project Sdk="Microsoft.NET.Sdk">
  403.   <ItemGroup>
  404.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  405.   </ItemGroup>
  406. </Project>}
  407. <Project Sdk="Microsoft.NET.Sdk">
  408.   <ItemGroup>
  409.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  410.   </ItemGroup>
  411. </Project><Project Sdk="Microsoft.NET.Sdk">
  412.   <ItemGroup>
  413.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  414.   </ItemGroup>
  415. </Project>yield return type;
  416. <Project Sdk="Microsoft.NET.Sdk">
  417.   <ItemGroup>
  418.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  419.   </ItemGroup>
  420. </Project>    }
  421. <Project Sdk="Microsoft.NET.Sdk">
  422.   <ItemGroup>
  423.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  424.   </ItemGroup>
  425. </Project>}
复制代码
  至此,我们就得到了一份可注册的元数据,它由一个实现类对应多个服务类。ClassMetadata 的定义如下:
  1.     /// <summary>
  2.     /// 类的元数据。
  3.     /// </summary>
  4.     public class ClassMetadata
  5.     {
  6. <Project Sdk="Microsoft.NET.Sdk">
  7.   <ItemGroup>
  8.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  9.   </ItemGroup>
  10. </Project>/// <summary>
  11. <Project Sdk="Microsoft.NET.Sdk">
  12.   <ItemGroup>
  13.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  14.   </ItemGroup>
  15. </Project>/// 初始化 <see cref="ClassMetadata"/> 类的新实例。
  16. <Project Sdk="Microsoft.NET.Sdk">
  17.   <ItemGroup>
  18.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  19.   </ItemGroup>
  20. </Project>/// </summary>
  21. <Project Sdk="Microsoft.NET.Sdk">
  22.   <ItemGroup>
  23.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  24.   </ItemGroup>
  25. </Project>/// <param name="implementationType">实现类的类型。</param>
  26. <Project Sdk="Microsoft.NET.Sdk">
  27.   <ItemGroup>
  28.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  29.   </ItemGroup>
  30. </Project>/// <param name="lifetime">生命周期。</param>
  31. <Project Sdk="Microsoft.NET.Sdk">
  32.   <ItemGroup>
  33.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  34.   </ItemGroup>
  35. </Project>public ClassMetadata(ITypeSymbol implementationType, string lifetime)
  36. <Project Sdk="Microsoft.NET.Sdk">
  37.   <ItemGroup>
  38.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  39.   </ItemGroup>
  40. </Project>{
  41. <Project Sdk="Microsoft.NET.Sdk">
  42.   <ItemGroup>
  43.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  44.   </ItemGroup>
  45. </Project>    ImplementationType = implementationType;
  46. <Project Sdk="Microsoft.NET.Sdk">
  47.   <ItemGroup>
  48.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  49.   </ItemGroup>
  50. </Project>    Lifetime = lifetime;
  51. <Project Sdk="Microsoft.NET.Sdk">
  52.   <ItemGroup>
  53.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  54.   </ItemGroup>
  55. </Project>}
  56. <Project Sdk="Microsoft.NET.Sdk">
  57.   <ItemGroup>
  58.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  59.   </ItemGroup>
  60. </Project>/// <summary>
  61. <Project Sdk="Microsoft.NET.Sdk">
  62.   <ItemGroup>
  63.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  64.   </ItemGroup>
  65. </Project>/// 获取实现类的类型。
  66. <Project Sdk="Microsoft.NET.Sdk">
  67.   <ItemGroup>
  68.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  69.   </ItemGroup>
  70. </Project>/// </summary>
  71. <Project Sdk="Microsoft.NET.Sdk">
  72.   <ItemGroup>
  73.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  74.   </ItemGroup>
  75. </Project>public ITypeSymbol ImplementationType { get; }
  76. <Project Sdk="Microsoft.NET.Sdk">
  77.   <ItemGroup>
  78.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  79.   </ItemGroup>
  80. </Project>/// <summary>
  81. <Project Sdk="Microsoft.NET.Sdk">
  82.   <ItemGroup>
  83.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  84.   </ItemGroup>
  85. </Project>/// 获取服务类的类型列表。
  86. <Project Sdk="Microsoft.NET.Sdk">
  87.   <ItemGroup>
  88.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  89.   </ItemGroup>
  90. </Project>/// </summary>
  91. <Project Sdk="Microsoft.NET.Sdk">
  92.   <ItemGroup>
  93.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  94.   </ItemGroup>
  95. </Project>public List<ITypeSymbol> ServiceTypes { get; } = new();
  96. <Project Sdk="Microsoft.NET.Sdk">
  97.   <ItemGroup>
  98.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  99.   </ItemGroup>
  100. </Project>/// <summary>
  101. <Project Sdk="Microsoft.NET.Sdk">
  102.   <ItemGroup>
  103.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  104.   </ItemGroup>
  105. </Project>/// 获取生命周期。
  106. <Project Sdk="Microsoft.NET.Sdk">
  107.   <ItemGroup>
  108.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  109.   </ItemGroup>
  110. </Project>/// </summary>
  111. <Project Sdk="Microsoft.NET.Sdk">
  112.   <ItemGroup>
  113.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  114.   </ItemGroup>
  115. </Project>public string Lifetime { get; }
  116. <Project Sdk="Microsoft.NET.Sdk">
  117.   <ItemGroup>
  118.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  119.   </ItemGroup>
  120. </Project>/// <summary>
  121. <Project Sdk="Microsoft.NET.Sdk">
  122.   <ItemGroup>
  123.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  124.   </ItemGroup>
  125. </Project>/// 添加服务类型。
  126. <Project Sdk="Microsoft.NET.Sdk">
  127.   <ItemGroup>
  128.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  129.   </ItemGroup>
  130. </Project>/// </summary>
  131. <Project Sdk="Microsoft.NET.Sdk">
  132.   <ItemGroup>
  133.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  134.   </ItemGroup>
  135. </Project>/// <param name="serviceTypes">服务类型列表。</param>
  136. <Project Sdk="Microsoft.NET.Sdk">
  137.   <ItemGroup>
  138.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  139.   </ItemGroup>
  140. </Project>/// <returns></returns>
  141. <Project Sdk="Microsoft.NET.Sdk">
  142.   <ItemGroup>
  143.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  144.   </ItemGroup>
  145. </Project>public ClassMetadata AddServiceTypes(IEnumerable<ITypeSymbol> serviceTypes)
  146. <Project Sdk="Microsoft.NET.Sdk">
  147.   <ItemGroup>
  148.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  149.   </ItemGroup>
  150. </Project>{
  151. <Project Sdk="Microsoft.NET.Sdk">
  152.   <ItemGroup>
  153.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  154.   </ItemGroup>
  155. </Project>    ServiceTypes.AddRange(serviceTypes);
  156. <Project Sdk="Microsoft.NET.Sdk">
  157.   <ItemGroup>
  158.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  159.   </ItemGroup>
  160. </Project>    return this;
  161. <Project Sdk="Microsoft.NET.Sdk">
  162.   <ItemGroup>
  163.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  164.   </ItemGroup>
  165. </Project>}
  166.     }
复制代码
  好了,得到这一份元数据后,我们转到 ServiceDiscoverGenerator,看看下一步它要做什么。
  1.     [Generator]
  2.     public class ServiceDiscoverGenerator : ISourceGenerator
  3.     {
  4. <Project Sdk="Microsoft.NET.Sdk">
  5.   <ItemGroup>
  6.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  7.   </ItemGroup>
  8. </Project>void ISourceGenerator.Initialize(GeneratorInitializationContext context)
  9. <Project Sdk="Microsoft.NET.Sdk">
  10.   <ItemGroup>
  11.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  12.   </ItemGroup>
  13. </Project>{
  14. <Project Sdk="Microsoft.NET.Sdk">
  15.   <ItemGroup>
  16.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  17.   </ItemGroup>
  18. </Project>    Debugger.Launch();
  19. <Project Sdk="Microsoft.NET.Sdk">
  20.   <ItemGroup>
  21.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  22.   </ItemGroup>
  23. </Project>    context.RegisterForSyntaxNotifications(() => new ServiceDiscoverSyntaxReceiver());
  24. <Project Sdk="Microsoft.NET.Sdk">
  25.   <ItemGroup>
  26.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  27.   </ItemGroup>
  28. </Project>}
  29. <Project Sdk="Microsoft.NET.Sdk">
  30.   <ItemGroup>
  31.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  32.   </ItemGroup>
  33. </Project>void ISourceGenerator.Execute(GeneratorExecutionContext context)
  34. <Project Sdk="Microsoft.NET.Sdk">
  35.   <ItemGroup>
  36.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  37.   </ItemGroup>
  38. </Project>{
  39. <Project Sdk="Microsoft.NET.Sdk">
  40.   <ItemGroup>
  41.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  42.   </ItemGroup>
  43. </Project>    if (context.SyntaxContextReceiver is ServiceDiscoverSyntaxReceiver receiver)
  44. <Project Sdk="Microsoft.NET.Sdk">
  45.   <ItemGroup>
  46.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  47.   </ItemGroup>
  48. </Project>    {
  49. <Project Sdk="Microsoft.NET.Sdk">
  50.   <ItemGroup>
  51.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  52.   </ItemGroup>
  53. </Project><Project Sdk="Microsoft.NET.Sdk">
  54.   <ItemGroup>
  55.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  56.   </ItemGroup>
  57. </Project>var metadatas = receiver.GetMetadatas();
  58. <Project Sdk="Microsoft.NET.Sdk">
  59.   <ItemGroup>
  60.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  61.   </ItemGroup>
  62. </Project><Project Sdk="Microsoft.NET.Sdk">
  63.   <ItemGroup>
  64.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  65.   </ItemGroup>
  66. </Project>if (metadatas.Count > 0)
  67. <Project Sdk="Microsoft.NET.Sdk">
  68.   <ItemGroup>
  69.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  70.   </ItemGroup>
  71. </Project><Project Sdk="Microsoft.NET.Sdk">
  72.   <ItemGroup>
  73.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  74.   </ItemGroup>
  75. </Project>{
  76. <Project Sdk="Microsoft.NET.Sdk">
  77.   <Target Name="_IncludeAllDependencies" BeforeTargets="_GetPackageFiles">
  78.     <ItemGroup>
  79. <Project Sdk="Microsoft.NET.Sdk">
  80.   <ItemGroup>
  81.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  82.   </ItemGroup>
  83. </Project><None Include="..\Fireasy.Common.Analyzers\bin\$(Configuration)\**\*.dll" Pack="True" PackagePath="analyzers\dotnet\cs" />
  84.     </ItemGroup>
  85.   </Target>
  86. </Project>context.AddSource("ServicesDiscover.cs", BuildDiscoverSourceCode(metadatas));
  87. <Project Sdk="Microsoft.NET.Sdk">
  88.   <ItemGroup>
  89.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  90.   </ItemGroup>
  91. </Project><Project Sdk="Microsoft.NET.Sdk">
  92.   <ItemGroup>
  93.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  94.   </ItemGroup>
  95. </Project>}
  96. <Project Sdk="Microsoft.NET.Sdk">
  97.   <ItemGroup>
  98.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  99.   </ItemGroup>
  100. </Project>    }
  101. <Project Sdk="Microsoft.NET.Sdk">
  102.   <ItemGroup>
  103.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  104.   </ItemGroup>
  105. </Project>}
  106.     }
复制代码
  在 Execute 方法中,拿到接收器分析出来的元数据,通过 BuildDiscoverSourceCode 方法去生成一段源代码。它是一个服务部署类,在 Configure 方法中,会把所有的服务描述添加到 IServiceCollection 容器内,如下:
  1. <Project Sdk="Microsoft.NET.Sdk">
  2.   <ItemGroup>
  3.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  4.   </ItemGroup>
  5. </Project>private SourceText BuildDiscoverSourceCode(List<ClassMetadata> metadatas)
  6. <Project Sdk="Microsoft.NET.Sdk">
  7.   <ItemGroup>
  8.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  9.   </ItemGroup>
  10. </Project>{
  11. <Project Sdk="Microsoft.NET.Sdk">
  12.   <ItemGroup>
  13.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  14.   </ItemGroup>
  15. </Project>    var sb = new StringBuilder();
  16. <Project Sdk="Microsoft.NET.Sdk">
  17.   <ItemGroup>
  18.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  19.   </ItemGroup>
  20. </Project>    sb.AppendLine(@"
  21. using Fireasy.Common.DependencyInjection;
  22. using Fireasy.Common.DynamicProxy;
  23. using Microsoft.Extensions.DependencyInjection;
  24. [assembly: Fireasy.Common.DependencyInjection.ServicesDeployAttribute(typeof(__ServiceDiscoverNs.__ServiceDiscoverServicesDeployer), Priority = 1)]
  25. namespace __ServiceDiscoverNs
  26. {
  27.     internal class __ServiceDiscoverServicesDeployer: IServicesDeployer
  28.     {
  29. <Project Sdk="Microsoft.NET.Sdk">
  30.   <ItemGroup>
  31.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  32.   </ItemGroup>
  33. </Project>void IServicesDeployer.Configure(IServiceCollection services)
  34. <Project Sdk="Microsoft.NET.Sdk">
  35.   <ItemGroup>
  36.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  37.   </ItemGroup>
  38. </Project>{");
  39. <Project Sdk="Microsoft.NET.Sdk">
  40.   <ItemGroup>
  41.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  42.   </ItemGroup>
  43. </Project>    foreach (var metadata in metadatas)
  44. <Project Sdk="Microsoft.NET.Sdk">
  45.   <ItemGroup>
  46.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  47.   </ItemGroup>
  48. </Project>    {
  49. <Project Sdk="Microsoft.NET.Sdk">
  50.   <ItemGroup>
  51.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  52.   </ItemGroup>
  53. </Project><Project Sdk="Microsoft.NET.Sdk">
  54.   <ItemGroup>
  55.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  56.   </ItemGroup>
  57. </Project>foreach (var svrType in metadata.ServiceTypes)
  58. <Project Sdk="Microsoft.NET.Sdk">
  59.   <ItemGroup>
  60.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  61.   </ItemGroup>
  62. </Project><Project Sdk="Microsoft.NET.Sdk">
  63.   <ItemGroup>
  64.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  65.   </ItemGroup>
  66. </Project>{
  67. <Project Sdk="Microsoft.NET.Sdk">
  68.   <Target Name="_IncludeAllDependencies" BeforeTargets="_GetPackageFiles">
  69.     <ItemGroup>
  70. <Project Sdk="Microsoft.NET.Sdk">
  71.   <ItemGroup>
  72.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  73.   </ItemGroup>
  74. </Project><None Include="..\Fireasy.Common.Analyzers\bin\$(Configuration)\**\*.dll" Pack="True" PackagePath="analyzers\dotnet\cs" />
  75.     </ItemGroup>
  76.   </Target>
  77. </Project>sb.AppendLine($"<Project Sdk="Microsoft.NET.Sdk">
  78.   <ItemGroup>
  79.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  80.   </ItemGroup>
  81. </Project>    services.Add{metadata.Lifetime}(typeof({GetTypeName(svrType)}), typeof({GetTypeName(metadata.ImplementationType)}));");
  82. <Project Sdk="Microsoft.NET.Sdk">
  83.   <ItemGroup>
  84.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  85.   </ItemGroup>
  86. </Project><Project Sdk="Microsoft.NET.Sdk">
  87.   <ItemGroup>
  88.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  89.   </ItemGroup>
  90. </Project>}
  91. <Project Sdk="Microsoft.NET.Sdk">
  92.   <ItemGroup>
  93.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  94.   </ItemGroup>
  95. </Project>    }
  96. <Project Sdk="Microsoft.NET.Sdk">
  97.   <ItemGroup>
  98.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  99.   </ItemGroup>
  100. </Project>    sb.AppendLine(@"
  101. <Project Sdk="Microsoft.NET.Sdk">
  102.   <ItemGroup>
  103.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  104.   </ItemGroup>
  105. </Project>}
  106.     }
  107. }");
  108. <Project Sdk="Microsoft.NET.Sdk">
  109.   <ItemGroup>
  110.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  111.   </ItemGroup>
  112. </Project>    return SourceText.From(sb.ToString(), Encoding.UTF8);
  113. <Project Sdk="Microsoft.NET.Sdk">
  114.   <ItemGroup>
  115.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  116.   </ItemGroup>
  117. </Project>}
  118. <Project Sdk="Microsoft.NET.Sdk">
  119.   <ItemGroup>
  120.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  121.   </ItemGroup>
  122. </Project>private string GetTypeName(ITypeSymbol symbol)
  123. <Project Sdk="Microsoft.NET.Sdk">
  124.   <ItemGroup>
  125.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  126.   </ItemGroup>
  127. </Project>{
  128. <Project Sdk="Microsoft.NET.Sdk">
  129.   <ItemGroup>
  130.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  131.   </ItemGroup>
  132. </Project>    if (symbol is INamedTypeSymbol namedTypeSymbol)
  133. <Project Sdk="Microsoft.NET.Sdk">
  134.   <ItemGroup>
  135.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  136.   </ItemGroup>
  137. </Project>    {
  138. <Project Sdk="Microsoft.NET.Sdk">
  139.   <ItemGroup>
  140.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  141.   </ItemGroup>
  142. </Project><Project Sdk="Microsoft.NET.Sdk">
  143.   <ItemGroup>
  144.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  145.   </ItemGroup>
  146. </Project>//如果是泛型,要处理成 Any<> 或 Any<,> 这样的描述
  147. <Project Sdk="Microsoft.NET.Sdk">
  148.   <ItemGroup>
  149.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  150.   </ItemGroup>
  151. </Project><Project Sdk="Microsoft.NET.Sdk">
  152.   <ItemGroup>
  153.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  154.   </ItemGroup>
  155. </Project>if (namedTypeSymbol.IsGenericType)
  156. <Project Sdk="Microsoft.NET.Sdk">
  157.   <ItemGroup>
  158.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  159.   </ItemGroup>
  160. </Project><Project Sdk="Microsoft.NET.Sdk">
  161.   <ItemGroup>
  162.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  163.   </ItemGroup>
  164. </Project>{
  165. <Project Sdk="Microsoft.NET.Sdk">
  166.   <Target Name="_IncludeAllDependencies" BeforeTargets="_GetPackageFiles">
  167.     <ItemGroup>
  168. <Project Sdk="Microsoft.NET.Sdk">
  169.   <ItemGroup>
  170.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  171.   </ItemGroup>
  172. </Project><None Include="..\Fireasy.Common.Analyzers\bin\$(Configuration)\**\*.dll" Pack="True" PackagePath="analyzers\dotnet\cs" />
  173.     </ItemGroup>
  174.   </Target>
  175. </Project>var t = namedTypeSymbol.ToDisplayString();
  176. <Project Sdk="Microsoft.NET.Sdk">
  177.   <Target Name="_IncludeAllDependencies" BeforeTargets="_GetPackageFiles">
  178.     <ItemGroup>
  179. <Project Sdk="Microsoft.NET.Sdk">
  180.   <ItemGroup>
  181.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  182.   </ItemGroup>
  183. </Project><None Include="..\Fireasy.Common.Analyzers\bin\$(Configuration)\**\*.dll" Pack="True" PackagePath="analyzers\dotnet\cs" />
  184.     </ItemGroup>
  185.   </Target>
  186. </Project>return t.Substring(0, t.IndexOf("<") + 1) + new string(',', namedTypeSymbol.TypeArguments.Length - 1) + ">";
  187. <Project Sdk="Microsoft.NET.Sdk">
  188.   <ItemGroup>
  189.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  190.   </ItemGroup>
  191. </Project><Project Sdk="Microsoft.NET.Sdk">
  192.   <ItemGroup>
  193.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  194.   </ItemGroup>
  195. </Project>}
  196. <Project Sdk="Microsoft.NET.Sdk">
  197.   <ItemGroup>
  198.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  199.   </ItemGroup>
  200. </Project>    }
  201. <Project Sdk="Microsoft.NET.Sdk">
  202.   <ItemGroup>
  203.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  204.   </ItemGroup>
  205. </Project>    return symbol.ToDisplayString();
  206. <Project Sdk="Microsoft.NET.Sdk">
  207.   <ItemGroup>
  208.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  209.   </ItemGroup>
  210. </Project>}
复制代码
  到这里,源代码生成器就算是完成了,那接下来怎么让它工作呢?
  首先,我们需要找到一个“宿主”,我之所以这么称呼,是因为 nuget 打包时,需要将分析器依附到一个包内,因此我选择 Fireasy.Common,在 Fireasy.Common 的项目文件中,加下以下一段代码,它的目的是当 Fireasy.Common 打包时,Fireasy.Common.Analyzers.dll 会自动打包到 analyzers 目录下,引用 Fireasy.Common 包时,会自动使用该分析器来生成代码。如下:
  1. <Project Sdk="Microsoft.NET.Sdk">
  2.   <Target Name="_IncludeAllDependencies" BeforeTargets="_GetPackageFiles">
  3.     <ItemGroup>
  4. <Project Sdk="Microsoft.NET.Sdk">
  5.   <ItemGroup>
  6.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  7.   </ItemGroup>
  8. </Project><None Include="..\Fireasy.Common.Analyzers\bin\$(Configuration)\**\*.dll" Pack="True" PackagePath="analyzers\dotnet\cs" />
  9.     </ItemGroup>
  10.   </Target>
  11. </Project>
复制代码
  我们测试的时候,因为是直接引用的项目,因此需要引用包含分析器的项目,而且要加上 OutputItemType 和 ReferenceOutputAssembly,如下:
  1. <Project Sdk="Microsoft.NET.Sdk">
  2.   <ItemGroup>
  3.     <ProjectReference Include="..\..\libraries\Fireasy.Common.Analyzers\Fireasy.Common.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  4.   </ItemGroup>
  5. </Project>
复制代码
  好了,编译测试项目,使用 ILSpy 反编译 dll 文件,你会发现,实现了 ISingletonService、ITransientService 或 IScopedService 的类自动注册进来了:
  1. // __ServiceDiscoverNs.__ServiceDiscoverServicesDeployer
  2. using Fireasy.Common.DependencyInjection;
  3. using Fireasy.Common.Tests;
  4. using Microsoft.Extensions.DependencyInjection;
  5. void IServicesDeployer.Configure(IServiceCollection services)
  6. {
  7.         services.AddSingleton(typeof(DependencyInjectionTests.ITestSingletonService), typeof(DependencyInjectionTests.TestSingletonServiceImpl));
  8.         services.AddTransient(typeof(DependencyInjectionTests.ITestTransientService), typeof(DependencyInjectionTests.TestTransientServiceImpl));
  9.         services.AddScoped(typeof(DependencyInjectionTests.ITestScopedService), typeof(DependencyInjectionTests.TestScopedServiceImpl));
  10.         services.AddTransient(typeof(DependencyInjectionTests.ITestWithRegisterAttr), typeof(DependencyInjectionTests.TestWithRegisterAttrImpl));
  11.         services.AddTransient(typeof(DependencyInjectionTests.TestWithRegisterAttrNonIntefaceImpl), typeof(DependencyInjectionTests.TestWithRegisterAttrNonIntefaceImpl));
  12.         services.AddTransient(typeof(DependencyInjectionTests.IGenericService<, >), typeof(DependencyInjectionTests.GenericService<, >));
  13.         services.AddTransient(typeof(DependencyInjectionTests.TestDynamicProxyClass), typeof(DependencyInjectionTests.TestDynamicProxyClass));
  14.         services.AddTransient(typeof(ObjectActivatorTests.ITestService), typeof(ObjectActivatorTests.TestService));
  15. }
复制代码
  另外还有一个小窍门,在测试项目的“依赖项”--“分析器”下,你会看到一个属于自己的分析器,依次展开,也会找到所生成的那个代码文件。

  最后,奉上 Fireasy 3 的开源地址:https://gitee.com/faib920/fireasy3 ,欢迎大家前来捧场。
  本文相关代码请参考:
  https://gitee.com/faib920/fireasy3/src/libraries/Fireasy.Common.Analyzers/ServiceDiscover
  https://gitee.com/faib920/fireasy3/tests/Fireasy.Common.Tests/DependencyInjectionTests.cs
  更多内容请移步官网 http://www.fireasy.cn 。

来源:https://www.cnblogs.com/fireasy/archive/2023/03/03/17174121.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具