优化复杂类型增量源生成器
This commit is contained in:
parent
53e6bb252a
commit
bca7202558
@ -1,5 +1,6 @@
|
|||||||
using Microsoft.CodeAnalysis;
|
using Microsoft.CodeAnalysis;
|
||||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@ -8,7 +9,7 @@ using System.Text;
|
|||||||
namespace JiShe.CollectBus.IncrementalGenerator
|
namespace JiShe.CollectBus.IncrementalGenerator
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 复杂类型源生成器
|
/// 复杂类型增量源生成器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Generator(LanguageNames.CSharp)]
|
[Generator(LanguageNames.CSharp)]
|
||||||
public class ComplexTypeSourceAnalyzers : IIncrementalGenerator
|
public class ComplexTypeSourceAnalyzers : IIncrementalGenerator
|
||||||
@ -32,11 +33,11 @@ namespace JiShe.CollectBus.IncrementalGenerator
|
|||||||
var compilationAndClasses = context.CompilationProvider.Combine(classDeclarations.Collect());
|
var compilationAndClasses = context.CompilationProvider.Combine(classDeclarations.Collect());
|
||||||
|
|
||||||
context.RegisterSourceOutput(compilationAndClasses, (spc, source) =>
|
context.RegisterSourceOutput(compilationAndClasses, (spc, source) =>
|
||||||
GenerateCode(source.Left, source.Right!, spc));
|
GenerateCode(source.Left, source.Right!, spc));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsClassWithAttribute(SyntaxNode node) => node is ClassDeclarationSyntax cds && cds.AttributeLists.Count > 0;
|
private static bool IsClassWithAttribute(SyntaxNode node) => node is ClassDeclarationSyntax cds && cds.AttributeLists.Count > 0;
|
||||||
|
|
||||||
private static ClassDeclarationSyntax GetClassDeclaration(GeneratorSyntaxContext context)
|
private static ClassDeclarationSyntax GetClassDeclaration(GeneratorSyntaxContext context)
|
||||||
{
|
{
|
||||||
var classDecl = (ClassDeclarationSyntax)context.Node;
|
var classDecl = (ClassDeclarationSyntax)context.Node;
|
||||||
@ -106,44 +107,14 @@ namespace JiShe.CollectBus.IncrementalGenerator
|
|||||||
Location.None));
|
Location.None));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//context.ReportDiagnostic(Diagnostic.Create(
|
var code = BuildAccessorsForType(classSymbol, compilation, processedTypes);
|
||||||
//new DiagnosticDescriptor(
|
|
||||||
// "PA001",
|
|
||||||
// "Generated Accessors",
|
|
||||||
// $"Generating accessors for {classSymbol.Name}",
|
|
||||||
// "Performance",
|
|
||||||
// DiagnosticSeverity.Info,
|
|
||||||
// true),
|
|
||||||
//Location.None));
|
|
||||||
|
|
||||||
//// 新增:输出继承链信息
|
|
||||||
//context.ReportDiagnostic(Diagnostic.Create(
|
|
||||||
// new DiagnosticDescriptor("HIERARCHY", "Class Hierarchy",
|
|
||||||
// $"Processing class: {classSymbol.Name}, BaseType: {classSymbol.BaseType?.Name}",
|
|
||||||
// "Debug", DiagnosticSeverity.Info, true),
|
|
||||||
// Location.None));
|
|
||||||
|
|
||||||
//context.ReportDiagnostic(Diagnostic.Create(
|
|
||||||
//new DiagnosticDescriptor("PA002", "Class Found",
|
|
||||||
//$"Processing class: {classSymbol.Name}", "Debug", DiagnosticSeverity.Warning, true),
|
|
||||||
//Location.None));
|
|
||||||
|
|
||||||
var code = BuildAccessorsForType(classSymbol, compilation, processedTypes);
|
|
||||||
|
|
||||||
//System.Diagnostics.Debug.WriteLine($"Generated code for {classSymbol.Name}:\n{code}"); // 调试输出
|
|
||||||
|
|
||||||
context.AddSource($"{classSymbol.Name}Extension.g.cs", code);
|
context.AddSource($"{classSymbol.Name}Extension.g.cs", code);
|
||||||
|
|
||||||
|
|
||||||
var code3 = BuildAccessorsForType2(classSymbol, compilation, processedTypes);
|
var code3 = BuildAccessorsForSourceEntity(classSymbol, compilation, processedTypes);
|
||||||
context.AddSource($"{classSymbol.Name}Accessor.g.cs", code3);
|
context.AddSource($"{classSymbol.Name}Accessor.g.cs", code3);
|
||||||
|
|
||||||
//code.AppendLine($"namespace {classSymbol.ContainingNamespace.ToDisplayString()};");
|
|
||||||
//if (classSymbol.ContainingNamespace.ToDisplayString() == "JiShe.CollectBus.IoTDB")
|
|
||||||
//{
|
|
||||||
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 生成工厂注册代码
|
// 生成工厂注册代码
|
||||||
@ -183,52 +154,6 @@ namespace JiShe.CollectBus.IncrementalGenerator
|
|||||||
return code.ToString();
|
return code.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 构建类的属性访问器代码
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="classSymbol"></param>
|
|
||||||
/// <param name="compilation"></param>
|
|
||||||
/// <param name="processedTypes"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
private static string BuildAccessorsForType2(
|
|
||||||
INamedTypeSymbol classSymbol,
|
|
||||||
Compilation compilation,
|
|
||||||
HashSet<ITypeSymbol> processedTypes)
|
|
||||||
{
|
|
||||||
var code = new StringBuilder();
|
|
||||||
code.AppendLine("#pragma warning disable CS0419 // 禁用警告");
|
|
||||||
code.AppendLine("// Generated code for " + classSymbol.Name);
|
|
||||||
code.AppendLine("// <auto-generated/>");
|
|
||||||
code.AppendLine("#nullable enable");
|
|
||||||
code.AppendLine($"namespace {classSymbol.ContainingNamespace.ToDisplayString()};");
|
|
||||||
code.AppendLine();
|
|
||||||
|
|
||||||
code.AppendLine($"public sealed class {classSymbol.Name}Accessor : ISourceEntityAccessor<{classSymbol.Name}>");
|
|
||||||
code.AppendLine("{");
|
|
||||||
|
|
||||||
foreach (var prop in GetAllPropertiesInHierarchy(classSymbol))
|
|
||||||
{
|
|
||||||
if (prop.IsIndexer) continue;
|
|
||||||
GeneratePropertyAccessorsForType(prop, code, compilation, processedTypes);
|
|
||||||
}
|
|
||||||
|
|
||||||
code.AppendLine("}");
|
|
||||||
|
|
||||||
//var code3 = $@"
|
|
||||||
// public sealed class {classSymbol.Name}Accessor : ISourceEntityAccessor<{classSymbol.Name}>
|
|
||||||
// {{
|
|
||||||
// public object GetPropertyValue({classSymbol.Name} entity, string propName) => propName switch
|
|
||||||
// {{
|
|
||||||
// {GeneratePropertyCases(classSymbol)}
|
|
||||||
// _ => throw new ArgumentException(""无效属性名"")
|
|
||||||
// }};
|
|
||||||
|
|
||||||
// {GenerateTupleSupport(classSymbol)}
|
|
||||||
// }}";
|
|
||||||
|
|
||||||
return code.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取泛型参数
|
/// 获取泛型参数
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -262,11 +187,11 @@ namespace JiShe.CollectBus.IncrementalGenerator
|
|||||||
// 处理元组类型
|
// 处理元组类型
|
||||||
if (propType is INamedTypeSymbol { IsTupleType: true } tupleType)
|
if (propType is INamedTypeSymbol { IsTupleType: true } tupleType)
|
||||||
{
|
{
|
||||||
GenerateTupleAccessors(prop, tupleType, code);
|
GenerateTupleAccessorsForType(prop, tupleType, code);
|
||||||
}
|
}
|
||||||
else if (propType is INamedTypeSymbol namedType)
|
else if (propType is INamedTypeSymbol namedType)
|
||||||
{
|
{
|
||||||
GenerateStandardAccessors(prop, namedType, code);
|
GenerateStandardAccessorsForType(prop, namedType, code);
|
||||||
ProcessNestedType(namedType, compilation, processedTypes);
|
ProcessNestedType(namedType, compilation, processedTypes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -277,7 +202,7 @@ namespace JiShe.CollectBus.IncrementalGenerator
|
|||||||
/// <param name="prop"></param>
|
/// <param name="prop"></param>
|
||||||
/// <param name="tupleType"></param>
|
/// <param name="tupleType"></param>
|
||||||
/// <param name="code"></param>
|
/// <param name="code"></param>
|
||||||
private static void GenerateTupleAccessors(IPropertySymbol prop, INamedTypeSymbol tupleType, StringBuilder code)
|
private static void GenerateTupleAccessorsForType(IPropertySymbol prop, INamedTypeSymbol tupleType, StringBuilder code)
|
||||||
{
|
{
|
||||||
var elements = tupleType.TupleElements;
|
var elements = tupleType.TupleElements;
|
||||||
var parentType = prop.ContainingType.ToDisplayString();
|
var parentType = prop.ContainingType.ToDisplayString();
|
||||||
@ -305,7 +230,7 @@ namespace JiShe.CollectBus.IncrementalGenerator
|
|||||||
/// <param name="prop"></param>
|
/// <param name="prop"></param>
|
||||||
/// <param name="propType"></param>
|
/// <param name="propType"></param>
|
||||||
/// <param name="code"></param>
|
/// <param name="code"></param>
|
||||||
private static void GenerateStandardAccessors(IPropertySymbol prop, INamedTypeSymbol propType, StringBuilder code)
|
private static void GenerateStandardAccessorsForType(IPropertySymbol prop, INamedTypeSymbol propType, StringBuilder code)
|
||||||
{
|
{
|
||||||
var parentType = prop.ContainingType.ToDisplayString();
|
var parentType = prop.ContainingType.ToDisplayString();
|
||||||
code.AppendLine($" public static {propType.ToDisplayString()} Get{prop.Name}({parentType} obj) => obj.{prop.Name};");
|
code.AppendLine($" public static {propType.ToDisplayString()} Get{prop.Name}({parentType} obj) => obj.{prop.Name};");
|
||||||
@ -316,7 +241,7 @@ namespace JiShe.CollectBus.IncrementalGenerator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 处理嵌套类型
|
/// 处理嵌套类型
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -373,5 +298,153 @@ namespace JiShe.CollectBus.IncrementalGenerator
|
|||||||
}
|
}
|
||||||
""";
|
""";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构建实体类的源属性访问器代码
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="classSymbol"></param>
|
||||||
|
/// <param name="compilation"></param>
|
||||||
|
/// <param name="processedTypes"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static string BuildAccessorsForSourceEntity(
|
||||||
|
INamedTypeSymbol classSymbol,
|
||||||
|
Compilation compilation,
|
||||||
|
HashSet<ITypeSymbol> processedTypes)
|
||||||
|
{
|
||||||
|
var code = new StringBuilder();
|
||||||
|
code.AppendLine("#pragma warning disable CS0419 // 禁用警告");
|
||||||
|
code.AppendLine("// Generated code for " + classSymbol.Name);
|
||||||
|
code.AppendLine("// <auto-generated/>");
|
||||||
|
code.AppendLine("#nullable enable");
|
||||||
|
code.AppendLine("using System;");
|
||||||
|
code.AppendLine("using JiShe.CollectBus.Analyzers.Shared;");
|
||||||
|
code.AppendLine($"namespace {classSymbol.ContainingNamespace.ToDisplayString()};");
|
||||||
|
code.AppendLine();
|
||||||
|
|
||||||
|
code.AppendLine($"public sealed class {classSymbol.Name}Accessor : ISourceEntityAccessor<{classSymbol.Name}>");
|
||||||
|
code.AppendLine("{");
|
||||||
|
|
||||||
|
GetGeneratePropertyValueForSourceEntity(GetAllPropertiesInHierarchy(classSymbol), code, compilation, classSymbol);
|
||||||
|
|
||||||
|
SetGeneratePropertyValueForSourceEntity(GetAllPropertiesInHierarchy(classSymbol), code, compilation, classSymbol);
|
||||||
|
|
||||||
|
code.AppendLine("}");
|
||||||
|
|
||||||
|
return code.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GetGeneratePropertyValueForSourceEntity(IEnumerable<IPropertySymbol> propList,
|
||||||
|
StringBuilder code,
|
||||||
|
Compilation compilation,
|
||||||
|
INamedTypeSymbol classSymbol)
|
||||||
|
{
|
||||||
|
|
||||||
|
code.AppendLine($" public object GetPropertyValue({classSymbol.Name} targetEntity, string propertyName)");
|
||||||
|
code.AppendLine(" {");
|
||||||
|
code.AppendLine(" return propertyName switch");
|
||||||
|
code.AppendLine(" {");
|
||||||
|
|
||||||
|
// 遍历所有属性
|
||||||
|
foreach (var property in propList)
|
||||||
|
{
|
||||||
|
// 安全类型转换
|
||||||
|
if (property.Type is not ITypeSymbol propType) continue;
|
||||||
|
|
||||||
|
// 处理元组类型
|
||||||
|
if (propType is INamedTypeSymbol { IsTupleType: true } tupleType)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
else if (propType is INamedTypeSymbol namedType)
|
||||||
|
{
|
||||||
|
// 生成属性访问的
|
||||||
|
code.AppendLine($" \"{property.Name}\" => {classSymbol.Name}Extension.Get{property.Name}(targetEntity),");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
code.AppendLine(" _ => throw new ArgumentException($\"Unknown property: {propertyName}\")");
|
||||||
|
code.AppendLine(" };");
|
||||||
|
code.AppendLine(" }");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void SetGeneratePropertyValueForSourceEntity(IEnumerable<IPropertySymbol> propList,
|
||||||
|
StringBuilder code,
|
||||||
|
Compilation compilation,
|
||||||
|
INamedTypeSymbol classSymbol)
|
||||||
|
{
|
||||||
|
code.AppendLine($" public void SetPropertyValue({classSymbol.Name} targetEntity, string propertyName, object value)");
|
||||||
|
code.AppendLine(" {");
|
||||||
|
code.AppendLine(" return propertyName switch");
|
||||||
|
code.AppendLine(" {");
|
||||||
|
|
||||||
|
// 遍历所有属性
|
||||||
|
foreach (var property in propList)
|
||||||
|
{
|
||||||
|
// 安全类型转换
|
||||||
|
if (property.Type is not ITypeSymbol propType) continue;
|
||||||
|
|
||||||
|
// 处理元组类型
|
||||||
|
if (propType is INamedTypeSymbol { IsTupleType: true } tupleType)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
else if (propType is INamedTypeSymbol namedType)
|
||||||
|
{
|
||||||
|
// 生成属性设置赋值
|
||||||
|
code.AppendLine($" \"{property.Name}\" => {classSymbol.Name}Extension.Set{property.Name}(targetEntity,({namedType.ToDisplayString()})value),");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
code.AppendLine(" _ => throw new ArgumentException($\"Unknown property: {propertyName}\")");
|
||||||
|
code.AppendLine(" };");
|
||||||
|
code.AppendLine(" }");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 处理元组类型
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="prop"></param>
|
||||||
|
/// <param name="tupleType"></param>
|
||||||
|
/// <param name="code"></param>
|
||||||
|
private static void GenerateTupleAccessorsForSourceEntity(IPropertySymbol prop, INamedTypeSymbol tupleType, StringBuilder code)
|
||||||
|
{
|
||||||
|
var elements = tupleType.TupleElements;
|
||||||
|
var parentType = prop.ContainingType.ToDisplayString();
|
||||||
|
|
||||||
|
for (int i = 0; i < elements.Length; i++)
|
||||||
|
{
|
||||||
|
var element = elements[i];
|
||||||
|
if (element.Type is not ITypeSymbol elementType) continue;
|
||||||
|
|
||||||
|
var elementName = element.CorrespondingTupleField?.Name ?? $"Item{i + 1}";
|
||||||
|
code.AppendLine($" public static {elementType.ToDisplayString()} Get{prop.Name}_{elementName}({parentType} obj) => obj.{prop.Name}.{elementName};");
|
||||||
|
|
||||||
|
if (prop.SetMethod != null)
|
||||||
|
{
|
||||||
|
var assignments = elements.Select((e, idx) =>
|
||||||
|
idx == i ? "value" : $"obj.{prop.Name}.{e.Name}");
|
||||||
|
code.AppendLine($" public static void Set{prop.Name}_{elementName}({parentType} obj, {elementType.ToDisplayString()} value) => obj.{prop.Name} = ({string.Join(", ", assignments)});");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 生成标准属性的访问器
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="prop"></param>
|
||||||
|
/// <param name="propType"></param>
|
||||||
|
/// <param name="code"></param>
|
||||||
|
private static void GenerateStandardAccessorsForSourceEntity(IPropertySymbol prop, INamedTypeSymbol propType, StringBuilder code)
|
||||||
|
{
|
||||||
|
var parentType = prop.ContainingType.ToDisplayString();
|
||||||
|
code.AppendLine($" public object {propType.ToDisplayString()} Get{prop.Name}({parentType} obj) => obj.{prop.Name};");
|
||||||
|
|
||||||
|
if (prop.SetMethod != null)
|
||||||
|
{
|
||||||
|
code.AppendLine($" public static void Set{prop.Name}({parentType} obj, {propType.ToDisplayString()} value) => obj.{prop.Name} = value;");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -8,7 +8,7 @@ namespace JiShe.CollectBus.IoTDB.Model
|
|||||||
/// Table模型单项数据实体
|
/// Table模型单项数据实体
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[EntityType(EntityTypeEnum.TableModel)]
|
[EntityType(EntityTypeEnum.TableModel)]
|
||||||
[SourceAnalyzers]
|
//[SourceAnalyzers]
|
||||||
public class TableModelSingleMeasuringEntity<T> : IoTEntity
|
public class TableModelSingleMeasuringEntity<T> : IoTEntity
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -8,7 +8,7 @@ namespace JiShe.CollectBus.IoTDB.Model
|
|||||||
/// Tree模型单项数据实体
|
/// Tree模型单项数据实体
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[EntityType(EntityTypeEnum.TreeModel)]
|
[EntityType(EntityTypeEnum.TreeModel)]
|
||||||
[SourceAnalyzers]
|
//[SourceAnalyzers]
|
||||||
public class TreeModelSingleMeasuringEntity<T> : IoTEntity
|
public class TreeModelSingleMeasuringEntity<T> : IoTEntity
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -72,6 +72,8 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS
|
|||||||
};
|
};
|
||||||
//ElectricityMeterTreeModelExtension.GetCurrent()
|
//ElectricityMeterTreeModelExtension.GetCurrent()
|
||||||
//SourceEntityAccessorFactory.SetCurrent(meter);
|
//SourceEntityAccessorFactory.SetCurrent(meter);
|
||||||
|
|
||||||
|
ElectricityMeterTreeModelAccessor
|
||||||
await _iotDBProvider.InsertAsync(meter);
|
await _iotDBProvider.InsertAsync(meter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -22,19 +22,19 @@ namespace JiShe.CollectBus.Analyzers.Shared
|
|||||||
/// <param name="value"></param>
|
/// <param name="value"></param>
|
||||||
void SetPropertyValue(T entity, string propertyName, object value);
|
void SetPropertyValue(T entity, string propertyName, object value);
|
||||||
|
|
||||||
/// <summary>
|
///// <summary>
|
||||||
/// 判断是否是元组属性
|
///// 判断是否是元组属性
|
||||||
/// </summary>
|
///// </summary>
|
||||||
/// <param name="propertyName"></param>
|
///// <param name="propertyName"></param>
|
||||||
/// <returns></returns>
|
///// <returns></returns>
|
||||||
bool IsTupleProperty(string propertyName);
|
//bool IsTupleProperty(string propertyName);
|
||||||
|
|
||||||
/// <summary>
|
///// <summary>
|
||||||
/// 获取元组属性值
|
///// 获取元组属性值
|
||||||
/// </summary>
|
///// </summary>
|
||||||
/// <param name="entity"></param>
|
///// <param name="entity"></param>
|
||||||
/// <param name="tuplePropertyName"></param>
|
///// <param name="tuplePropertyName"></param>
|
||||||
/// <returns></returns>
|
///// <returns></returns>
|
||||||
(object Item1, object Item2) GetTupleParts(T entity, string tuplePropertyName);
|
//(object Item1, object Item2) GetTupleParts(T entity, string tuplePropertyName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user