完善增量源码生成器
This commit is contained in:
parent
edecbc386e
commit
db7384ae74
@ -2,6 +2,7 @@
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
@ -105,7 +106,7 @@ namespace JiShe.CollectBus.IncrementalGenerator
|
||||
Location.None));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
var code3 = BuildAccessorsForSourceEntity(classSymbol, compilation, processedTypes);
|
||||
context.AddSource($"{classSymbol.Name}Accessor.g.cs", code3);
|
||||
}
|
||||
@ -113,7 +114,7 @@ namespace JiShe.CollectBus.IncrementalGenerator
|
||||
// 生成工厂注册代码
|
||||
context.AddSource("SourceEntityAccessorFactory.g.cs", BuildFactoryCode());
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取泛型参数
|
||||
/// </summary>
|
||||
@ -125,8 +126,8 @@ namespace JiShe.CollectBus.IncrementalGenerator
|
||||
var parameters = symbol.TypeParameters.Select(t => t.Name);
|
||||
return $"<{string.Join(", ", parameters)}>";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 生成标准属性的访问器
|
||||
/// </summary>
|
||||
@ -143,7 +144,7 @@ namespace JiShe.CollectBus.IncrementalGenerator
|
||||
code.AppendLine($" public static void Set{prop.Name}({parentType} obj, {propType.ToDisplayString()} value) => obj.{prop.Name} = value;");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 构建实体访问器代码(支持泛型)
|
||||
@ -179,21 +180,22 @@ namespace JiShe.CollectBus.IncrementalGenerator
|
||||
$": ISourceEntityAccessor<{classSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)}>");
|
||||
|
||||
code.AppendLine("{");
|
||||
|
||||
|
||||
var propList = GetAllPropertiesInHierarchy(classSymbol);
|
||||
|
||||
foreach (var prop in propList)
|
||||
{
|
||||
// 安全类型转换
|
||||
if (prop.Type is not ITypeSymbol propType) continue;
|
||||
|
||||
if (propType is INamedTypeSymbol namedType)
|
||||
{
|
||||
GenerateStandardAccessors(prop, namedType, code);
|
||||
}
|
||||
|
||||
if (propType is INamedTypeSymbol { IsTupleType: true } tupleType)
|
||||
{
|
||||
GenerateTupleAccessors(prop, tupleType, code, classSymbol);
|
||||
}
|
||||
else if (propType is INamedTypeSymbol namedType)
|
||||
{
|
||||
GenerateStandardAccessors(prop, namedType, code);
|
||||
GenerateTupleAccessors(prop, tupleType, code);
|
||||
}
|
||||
}
|
||||
|
||||
@ -201,70 +203,57 @@ namespace JiShe.CollectBus.IncrementalGenerator
|
||||
GeneratePropertyListForSourceEntity(propList, code, compilation, classSymbol);
|
||||
|
||||
//生成当前类属性信息集合
|
||||
GeneratePropertyInfoListForSourceEntity(
|
||||
propList,
|
||||
code,
|
||||
compilation,
|
||||
classSymbol);
|
||||
GenerateEntityMemberInfoList(propList, code, compilation, classSymbol);
|
||||
|
||||
|
||||
//生成当前类属性访问
|
||||
GetGeneratePropertyValueForSourceEntity(
|
||||
propList,
|
||||
code,
|
||||
compilation,
|
||||
classSymbol);
|
||||
GetGeneratePropertyValueForSourceEntity(propList, code, compilation, classSymbol);
|
||||
|
||||
//生成当前类属性设置
|
||||
SetGeneratePropertyValueForSourceEntity(
|
||||
propList,
|
||||
code,
|
||||
compilation,
|
||||
classSymbol);
|
||||
|
||||
SetGeneratePropertyValueForSourceEntity(propList, code, compilation, classSymbol);
|
||||
|
||||
code.AppendLine("}");
|
||||
return code.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 生成泛型ValueTuple 元组访问器
|
||||
/// </summary>
|
||||
private static void GenerateTupleAccessors(
|
||||
IPropertySymbol prop,
|
||||
INamedTypeSymbol tupleType,
|
||||
StringBuilder code,
|
||||
INamedTypeSymbol classSymbol)
|
||||
IPropertySymbol prop,
|
||||
INamedTypeSymbol tupleType,
|
||||
StringBuilder code)
|
||||
{
|
||||
var parentType = classSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
|
||||
var parentType = prop.ContainingType.ToDisplayString();
|
||||
var tupleElements = tupleType.TupleElements;
|
||||
|
||||
for (int i = 0; i < tupleElements.Length; i++)
|
||||
{
|
||||
var element = tupleElements[i];
|
||||
var elementType = element.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
|
||||
var elementType = element.Type.ToDisplayString();
|
||||
var elementName = element.Name;
|
||||
|
||||
// Getter保持不变
|
||||
code.AppendLine(
|
||||
$" public static {elementType} Get{prop.Name}_{elementName}" +
|
||||
$"({parentType} obj) => obj.{prop.Name}.{elementName};");
|
||||
// Getter
|
||||
code.AppendLine($"public static {elementType} Get{prop.Name}_{elementName}({parentType} obj) => obj.{prop.Name}.{elementName};");
|
||||
|
||||
// Setter修复:使用元组字面量
|
||||
// Setter
|
||||
if (prop.SetMethod != null)
|
||||
{
|
||||
var valueExpressions = tupleElements.Select((e, idx) =>
|
||||
idx == i ? "value" : $"obj.{prop.Name}.{e.Name}"
|
||||
).ToList();
|
||||
|
||||
// 关键修复:生成正确的元组字面量表达式
|
||||
code.AppendLine(
|
||||
$" public static void Set{prop.Name}_{elementName}" +
|
||||
$"({parentType} obj, {elementType} value) => " +
|
||||
$"obj.{prop.Name} = ({string.Join(", ", valueExpressions)});");
|
||||
code.AppendLine($"public static void Set{prop.Name}_{elementName}({parentType} obj, {elementType} value) => obj.{prop.Name} = ({string.Join(", ", GetTupleElements(prop.Name, tupleElements, i))});");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<string> GetTupleElements(
|
||||
string propName,
|
||||
ImmutableArray<IFieldSymbol> elements,
|
||||
int targetIndex)
|
||||
{
|
||||
for (int i = 0; i < elements.Length; i++)
|
||||
{
|
||||
yield return i == targetIndex
|
||||
? "value"
|
||||
: $"obj.{propName}.{elements[i].Name}";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理System.Tuple类型的访问器生成
|
||||
/// </summary>
|
||||
@ -370,6 +359,10 @@ namespace JiShe.CollectBus.IncrementalGenerator
|
||||
|
||||
foreach (var prop in propList)
|
||||
{
|
||||
code.AppendLine(
|
||||
$" \"{prop.Name}\" => " +
|
||||
$"Get{prop.Name}(targetEntity),");
|
||||
|
||||
if (prop.Type is INamedTypeSymbol { IsTupleType: true } tupleType)
|
||||
{
|
||||
foreach (var element in tupleType.TupleElements)
|
||||
@ -379,12 +372,7 @@ namespace JiShe.CollectBus.IncrementalGenerator
|
||||
$"Get{prop.Name}_{element.Name}(targetEntity),");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
code.AppendLine(
|
||||
$" \"{prop.Name}\" => " +
|
||||
$"Get{prop.Name}(targetEntity),");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
code.AppendLine(" _ => throw new ArgumentException($\"Unknown property: {propertyName}\")");
|
||||
@ -412,6 +400,12 @@ namespace JiShe.CollectBus.IncrementalGenerator
|
||||
|
||||
foreach (var prop in propList)
|
||||
{
|
||||
var propType = prop.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
|
||||
code.AppendLine($" case \"{prop.Name}\":");
|
||||
code.AppendLine($" Set{prop.Name}(");
|
||||
code.AppendLine($" targetEntity, ({propType})value);");
|
||||
code.AppendLine(" break;");
|
||||
|
||||
if (prop.Type is INamedTypeSymbol { IsTupleType: true } tupleType)
|
||||
{
|
||||
foreach (var element in tupleType.TupleElements)
|
||||
@ -422,15 +416,7 @@ namespace JiShe.CollectBus.IncrementalGenerator
|
||||
code.AppendLine($" targetEntity, ({elementType})value);");
|
||||
code.AppendLine(" break;");
|
||||
}
|
||||
}
|
||||
else if (prop.SetMethod != null)
|
||||
{
|
||||
var propType = prop.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
|
||||
code.AppendLine($" case \"{prop.Name}\":");
|
||||
code.AppendLine($" Set{prop.Name}(");
|
||||
code.AppendLine($" targetEntity, ({propType})value);");
|
||||
code.AppendLine(" break;");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
code.AppendLine(" default:");
|
||||
@ -458,7 +444,7 @@ namespace JiShe.CollectBus.IncrementalGenerator
|
||||
foreach (var prop in propList)
|
||||
{
|
||||
if (prop.Type is INamedTypeSymbol { IsTupleType: true } tupleType)
|
||||
{
|
||||
{
|
||||
foreach (var element in tupleType.TupleElements)
|
||||
{
|
||||
tempPropList.Add($"\"{prop.Name}.{element.Name}\"");
|
||||
@ -477,52 +463,52 @@ namespace JiShe.CollectBus.IncrementalGenerator
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 生成当前类属性信息集合(支持嵌套元组)
|
||||
/// 生成当前类属性信息集合
|
||||
/// </summary>
|
||||
private static void GeneratePropertyInfoListForSourceEntity(
|
||||
private static void GenerateEntityMemberInfoList(
|
||||
IEnumerable<IPropertySymbol> propList,
|
||||
StringBuilder code,
|
||||
Compilation compilation,
|
||||
INamedTypeSymbol classSymbol)
|
||||
{
|
||||
code.AppendLine(" public List<System.Reflection.PropertyInfo> PropertyInfoList { get; } = new List<System.Reflection.PropertyInfo>");
|
||||
code.AppendLine(" public List<EntityMemberInfo> MemberList { get; } = new()");
|
||||
code.AppendLine(" {");
|
||||
|
||||
var initializerLines = new List<string>();
|
||||
|
||||
var index = 0;
|
||||
|
||||
foreach (var prop in propList)
|
||||
{
|
||||
AddPropertyInitializer(classSymbol, prop, initializerLines);
|
||||
var propType = prop.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
|
||||
var parentType = prop.ContainingType.ToDisplayString();
|
||||
// 主属性
|
||||
initializerLines.Add(
|
||||
$"new EntityMemberInfo(" +
|
||||
$"\"{prop.Name}\", " +
|
||||
$"typeof({parentType}), " +
|
||||
$"(e) => Get{prop.Name}(({parentType})e), " +
|
||||
$"(e, v) => Set{prop.Name}(({parentType})e, ({propType})v))");
|
||||
|
||||
// 元组元素
|
||||
if (prop.Type is INamedTypeSymbol { IsTupleType: true } tupleType)
|
||||
{
|
||||
foreach (var element in tupleType.TupleElements)
|
||||
{
|
||||
//使用GetField代替GetProperty
|
||||
var tupleTypeName = tupleType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
|
||||
var elementType = element.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
|
||||
var elementName = element.Name;
|
||||
|
||||
initializerLines.Add(
|
||||
$"typeof({tupleTypeName}).GetField(\"{element.Name}\") ?? " +
|
||||
$"throw new InvalidOperationException(\"Tuple field {element.Name} not found\")");
|
||||
$"new EntityMemberInfo(" +
|
||||
$"\"{prop.Name}.{elementName}\", " +
|
||||
$"typeof({elementType}), " +
|
||||
$"(e) => Get{prop.Name}_{elementName}(({parentType})e), " +
|
||||
$"(e, v) => Set{prop.Name}_{elementName}(({parentType})e, ({elementType})v))");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
code.AppendLine(string.Join(",\n", initializerLines));
|
||||
code.AppendLine(" };");
|
||||
}
|
||||
|
||||
private static void AddPropertyInitializer(
|
||||
INamedTypeSymbol classSymbol,
|
||||
IPropertySymbol prop,
|
||||
List<string> initializerLines)
|
||||
{
|
||||
var classType = classSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
|
||||
initializerLines.Add(
|
||||
$"typeof({classType}).GetProperty(\"{prop.Name}\", " +
|
||||
"System.Reflection.BindingFlags.Public | " +
|
||||
"System.Reflection.BindingFlags.Instance) ?? " +
|
||||
$"throw new InvalidOperationException(\"Property {prop.Name} not found\")");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -635,11 +635,11 @@ namespace JiShe.CollectBus.IoTDB.Provider
|
||||
{
|
||||
var columns = new List<ColumnInfo>();
|
||||
|
||||
foreach (var prop in accessor.PropertyInfoList)
|
||||
foreach (var prop in accessor.MemberList)
|
||||
{
|
||||
string typeName = string.Empty;
|
||||
|
||||
Type declaredType = prop.PropertyType;
|
||||
Type declaredType = prop.Type;
|
||||
// 处理可空类型
|
||||
if (declaredType.IsGenericType && declaredType.GetGenericTypeDefinition() == typeof(Nullable<>))
|
||||
{
|
||||
@ -652,25 +652,25 @@ namespace JiShe.CollectBus.IoTDB.Provider
|
||||
}
|
||||
|
||||
//先获取Tag标签和属性标签
|
||||
ColumnInfo? column = prop.GetCustomAttribute<TAGColumnAttribute>() is not null ? new ColumnInfo(
|
||||
name: prop.Name,
|
||||
ColumnInfo? column = declaredType.GetCustomAttribute<TAGColumnAttribute>() is not null ? new ColumnInfo(
|
||||
name: prop.Path,
|
||||
category: ColumnCategory.TAG,
|
||||
dataType: GetDataTypeFromTypeName(typeName),
|
||||
false
|
||||
) : prop.GetCustomAttribute<ATTRIBUTEColumnAttribute>() is not null ? new ColumnInfo(
|
||||
prop.Name,
|
||||
) : declaredType.GetCustomAttribute<ATTRIBUTEColumnAttribute>() is not null ? new ColumnInfo(
|
||||
prop.Path,
|
||||
ColumnCategory.ATTRIBUTE,
|
||||
GetDataTypeFromTypeName(typeName),
|
||||
false
|
||||
) : prop.GetCustomAttribute<FIELDColumnAttribute>() is not null ? new ColumnInfo(
|
||||
prop.Name,
|
||||
) : declaredType.GetCustomAttribute<FIELDColumnAttribute>() is not null ? new ColumnInfo(
|
||||
prop.Path,
|
||||
ColumnCategory.FIELD,
|
||||
GetDataTypeFromTypeName(typeName),
|
||||
false)
|
||||
: null;
|
||||
|
||||
//最先检查是不是单侧点模式
|
||||
SingleMeasuringAttribute singleMeasuringAttribute = prop.GetCustomAttribute<SingleMeasuringAttribute>();
|
||||
SingleMeasuringAttribute singleMeasuringAttribute = declaredType.GetCustomAttribute<SingleMeasuringAttribute>();
|
||||
|
||||
if (singleMeasuringAttribute != null && column == null)
|
||||
{
|
||||
@ -679,15 +679,15 @@ namespace JiShe.CollectBus.IoTDB.Provider
|
||||
//只有一个Filed字段。
|
||||
//MeasuringName 默认为 SingleMeasuringAttribute.FieldName,以便于在获取对应的Value的时候重置为 Item1 的值。
|
||||
|
||||
Type tupleType = prop.PropertyType;
|
||||
Type[] tupleArgs = tupleType.GetGenericArguments();
|
||||
//Type tupleType = prop.PropertyType;
|
||||
//Type[] tupleArgs = tupleType.GetGenericArguments();
|
||||
|
||||
column = new ColumnInfo(
|
||||
singleMeasuringAttribute.FieldName,
|
||||
ColumnCategory.FIELD,
|
||||
GetDataTypeFromTypeName(tupleArgs[1].Name),
|
||||
true
|
||||
);
|
||||
//column = new ColumnInfo(
|
||||
// singleMeasuringAttribute.FieldName,
|
||||
// ColumnCategory.FIELD,
|
||||
// GetDataTypeFromTypeName(tupleArgs[1].Name),
|
||||
// true
|
||||
//);
|
||||
}
|
||||
|
||||
if (column.HasValue)
|
||||
|
||||
@ -75,7 +75,7 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS
|
||||
|
||||
//ElectricityMeterTreeModelAccessor.
|
||||
//TableModelSingleMeasuringEntityExtension
|
||||
//TableModelSingleMeasuringEntityAccessor.GetSystemName(meter);
|
||||
//TableModelSingleMeasuringEntityAccessor.GetSystemName(meter);
|
||||
await _iotDBProvider.InsertAsync(meter);
|
||||
}
|
||||
|
||||
|
||||
@ -32,11 +32,11 @@ namespace JiShe.CollectBus.Ammeters
|
||||
public double Current { get; set; }
|
||||
|
||||
[FIELDColumn]
|
||||
public double Power => Voltage * Current;
|
||||
public double Power { get; set; }
|
||||
|
||||
[FIELDColumn]
|
||||
public double? Currentd { get; set; }
|
||||
|
||||
public Tuple<int,string> TupleData { get; set;}
|
||||
public ValueTuple<int, string> TupleData { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,6 +31,6 @@ namespace JiShe.CollectBus.Analyzers.Shared
|
||||
/// <summary>
|
||||
/// 属性信息集合
|
||||
/// </summary>
|
||||
List<PropertyInfo> PropertyInfoList { get; }
|
||||
List<EntityMemberInfo> MemberList { get; }
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user