完善增量源码生成器
This commit is contained in:
parent
edecbc386e
commit
db7384ae74
@ -2,6 +2,7 @@
|
|||||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Immutable;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@ -187,84 +188,72 @@ namespace JiShe.CollectBus.IncrementalGenerator
|
|||||||
// 安全类型转换
|
// 安全类型转换
|
||||||
if (prop.Type is not ITypeSymbol propType) continue;
|
if (prop.Type is not ITypeSymbol propType) continue;
|
||||||
|
|
||||||
if (propType is INamedTypeSymbol { IsTupleType: true } tupleType)
|
if (propType is INamedTypeSymbol namedType)
|
||||||
{
|
|
||||||
GenerateTupleAccessors(prop, tupleType, code, classSymbol);
|
|
||||||
}
|
|
||||||
else if (propType is INamedTypeSymbol namedType)
|
|
||||||
{
|
{
|
||||||
GenerateStandardAccessors(prop, namedType, code);
|
GenerateStandardAccessors(prop, namedType, code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (propType is INamedTypeSymbol { IsTupleType: true } tupleType)
|
||||||
|
{
|
||||||
|
GenerateTupleAccessors(prop, tupleType, code);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//生成当前类属性名称集合
|
//生成当前类属性名称集合
|
||||||
GeneratePropertyListForSourceEntity(propList, code, compilation, classSymbol);
|
GeneratePropertyListForSourceEntity(propList, code, compilation, classSymbol);
|
||||||
|
|
||||||
//生成当前类属性信息集合
|
//生成当前类属性信息集合
|
||||||
GeneratePropertyInfoListForSourceEntity(
|
GenerateEntityMemberInfoList(propList, code, compilation, classSymbol);
|
||||||
propList,
|
|
||||||
code,
|
|
||||||
compilation,
|
|
||||||
classSymbol);
|
|
||||||
|
|
||||||
|
|
||||||
//生成当前类属性访问
|
//生成当前类属性访问
|
||||||
GetGeneratePropertyValueForSourceEntity(
|
GetGeneratePropertyValueForSourceEntity(propList, code, compilation, classSymbol);
|
||||||
propList,
|
|
||||||
code,
|
|
||||||
compilation,
|
|
||||||
classSymbol);
|
|
||||||
|
|
||||||
//生成当前类属性设置
|
//生成当前类属性设置
|
||||||
SetGeneratePropertyValueForSourceEntity(
|
SetGeneratePropertyValueForSourceEntity(propList, code, compilation, classSymbol);
|
||||||
propList,
|
|
||||||
code,
|
|
||||||
compilation,
|
|
||||||
classSymbol);
|
|
||||||
|
|
||||||
code.AppendLine("}");
|
code.AppendLine("}");
|
||||||
return code.ToString();
|
return code.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 生成泛型ValueTuple 元组访问器
|
|
||||||
/// </summary>
|
|
||||||
private static void GenerateTupleAccessors(
|
private static void GenerateTupleAccessors(
|
||||||
IPropertySymbol prop,
|
IPropertySymbol prop,
|
||||||
INamedTypeSymbol tupleType,
|
INamedTypeSymbol tupleType,
|
||||||
StringBuilder code,
|
StringBuilder code)
|
||||||
INamedTypeSymbol classSymbol)
|
|
||||||
{
|
{
|
||||||
var parentType = classSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
|
var parentType = prop.ContainingType.ToDisplayString();
|
||||||
var tupleElements = tupleType.TupleElements;
|
var tupleElements = tupleType.TupleElements;
|
||||||
|
|
||||||
for (int i = 0; i < tupleElements.Length; i++)
|
for (int i = 0; i < tupleElements.Length; i++)
|
||||||
{
|
{
|
||||||
var element = tupleElements[i];
|
var element = tupleElements[i];
|
||||||
var elementType = element.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
|
var elementType = element.Type.ToDisplayString();
|
||||||
var elementName = element.Name;
|
var elementName = element.Name;
|
||||||
|
|
||||||
// Getter保持不变
|
// Getter
|
||||||
code.AppendLine(
|
code.AppendLine($"public static {elementType} Get{prop.Name}_{elementName}({parentType} obj) => obj.{prop.Name}.{elementName};");
|
||||||
$" public static {elementType} Get{prop.Name}_{elementName}" +
|
|
||||||
$"({parentType} obj) => obj.{prop.Name}.{elementName};");
|
|
||||||
|
|
||||||
// Setter修复:使用元组字面量
|
// Setter
|
||||||
if (prop.SetMethod != null)
|
if (prop.SetMethod != null)
|
||||||
{
|
{
|
||||||
var valueExpressions = tupleElements.Select((e, idx) =>
|
code.AppendLine($"public static void Set{prop.Name}_{elementName}({parentType} obj, {elementType} value) => obj.{prop.Name} = ({string.Join(", ", GetTupleElements(prop.Name, tupleElements, i))});");
|
||||||
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)});");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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>
|
/// <summary>
|
||||||
/// 处理System.Tuple类型的访问器生成
|
/// 处理System.Tuple类型的访问器生成
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -370,6 +359,10 @@ namespace JiShe.CollectBus.IncrementalGenerator
|
|||||||
|
|
||||||
foreach (var prop in propList)
|
foreach (var prop in propList)
|
||||||
{
|
{
|
||||||
|
code.AppendLine(
|
||||||
|
$" \"{prop.Name}\" => " +
|
||||||
|
$"Get{prop.Name}(targetEntity),");
|
||||||
|
|
||||||
if (prop.Type is INamedTypeSymbol { IsTupleType: true } tupleType)
|
if (prop.Type is INamedTypeSymbol { IsTupleType: true } tupleType)
|
||||||
{
|
{
|
||||||
foreach (var element in tupleType.TupleElements)
|
foreach (var element in tupleType.TupleElements)
|
||||||
@ -379,12 +372,7 @@ namespace JiShe.CollectBus.IncrementalGenerator
|
|||||||
$"Get{prop.Name}_{element.Name}(targetEntity),");
|
$"Get{prop.Name}_{element.Name}(targetEntity),");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
code.AppendLine(
|
|
||||||
$" \"{prop.Name}\" => " +
|
|
||||||
$"Get{prop.Name}(targetEntity),");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
code.AppendLine(" _ => throw new ArgumentException($\"Unknown property: {propertyName}\")");
|
code.AppendLine(" _ => throw new ArgumentException($\"Unknown property: {propertyName}\")");
|
||||||
@ -412,6 +400,12 @@ namespace JiShe.CollectBus.IncrementalGenerator
|
|||||||
|
|
||||||
foreach (var prop in propList)
|
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)
|
if (prop.Type is INamedTypeSymbol { IsTupleType: true } tupleType)
|
||||||
{
|
{
|
||||||
foreach (var element in tupleType.TupleElements)
|
foreach (var element in tupleType.TupleElements)
|
||||||
@ -423,14 +417,6 @@ namespace JiShe.CollectBus.IncrementalGenerator
|
|||||||
code.AppendLine(" break;");
|
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:");
|
code.AppendLine(" default:");
|
||||||
@ -477,33 +463,46 @@ namespace JiShe.CollectBus.IncrementalGenerator
|
|||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 生成当前类属性信息集合(支持嵌套元组)
|
/// 生成当前类属性信息集合
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static void GeneratePropertyInfoListForSourceEntity(
|
private static void GenerateEntityMemberInfoList(
|
||||||
IEnumerable<IPropertySymbol> propList,
|
IEnumerable<IPropertySymbol> propList,
|
||||||
StringBuilder code,
|
StringBuilder code,
|
||||||
Compilation compilation,
|
Compilation compilation,
|
||||||
INamedTypeSymbol classSymbol)
|
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(" {");
|
code.AppendLine(" {");
|
||||||
|
|
||||||
var initializerLines = new List<string>();
|
var initializerLines = new List<string>();
|
||||||
|
var index = 0;
|
||||||
|
|
||||||
foreach (var prop in propList)
|
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)
|
if (prop.Type is INamedTypeSymbol { IsTupleType: true } tupleType)
|
||||||
{
|
{
|
||||||
foreach (var element in tupleType.TupleElements)
|
foreach (var element in tupleType.TupleElements)
|
||||||
{
|
{
|
||||||
//使用GetField代替GetProperty
|
var elementType = element.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
|
||||||
var tupleTypeName = tupleType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
|
var elementName = element.Name;
|
||||||
|
|
||||||
initializerLines.Add(
|
initializerLines.Add(
|
||||||
$"typeof({tupleTypeName}).GetField(\"{element.Name}\") ?? " +
|
$"new EntityMemberInfo(" +
|
||||||
$"throw new InvalidOperationException(\"Tuple field {element.Name} not found\")");
|
$"\"{prop.Name}.{elementName}\", " +
|
||||||
|
$"typeof({elementType}), " +
|
||||||
|
$"(e) => Get{prop.Name}_{elementName}(({parentType})e), " +
|
||||||
|
$"(e, v) => Set{prop.Name}_{elementName}(({parentType})e, ({elementType})v))");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -511,18 +510,5 @@ namespace JiShe.CollectBus.IncrementalGenerator
|
|||||||
code.AppendLine(string.Join(",\n", initializerLines));
|
code.AppendLine(string.Join(",\n", initializerLines));
|
||||||
code.AppendLine(" };");
|
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>();
|
var columns = new List<ColumnInfo>();
|
||||||
|
|
||||||
foreach (var prop in accessor.PropertyInfoList)
|
foreach (var prop in accessor.MemberList)
|
||||||
{
|
{
|
||||||
string typeName = string.Empty;
|
string typeName = string.Empty;
|
||||||
|
|
||||||
Type declaredType = prop.PropertyType;
|
Type declaredType = prop.Type;
|
||||||
// 处理可空类型
|
// 处理可空类型
|
||||||
if (declaredType.IsGenericType && declaredType.GetGenericTypeDefinition() == typeof(Nullable<>))
|
if (declaredType.IsGenericType && declaredType.GetGenericTypeDefinition() == typeof(Nullable<>))
|
||||||
{
|
{
|
||||||
@ -652,25 +652,25 @@ namespace JiShe.CollectBus.IoTDB.Provider
|
|||||||
}
|
}
|
||||||
|
|
||||||
//先获取Tag标签和属性标签
|
//先获取Tag标签和属性标签
|
||||||
ColumnInfo? column = prop.GetCustomAttribute<TAGColumnAttribute>() is not null ? new ColumnInfo(
|
ColumnInfo? column = declaredType.GetCustomAttribute<TAGColumnAttribute>() is not null ? new ColumnInfo(
|
||||||
name: prop.Name,
|
name: prop.Path,
|
||||||
category: ColumnCategory.TAG,
|
category: ColumnCategory.TAG,
|
||||||
dataType: GetDataTypeFromTypeName(typeName),
|
dataType: GetDataTypeFromTypeName(typeName),
|
||||||
false
|
false
|
||||||
) : prop.GetCustomAttribute<ATTRIBUTEColumnAttribute>() is not null ? new ColumnInfo(
|
) : declaredType.GetCustomAttribute<ATTRIBUTEColumnAttribute>() is not null ? new ColumnInfo(
|
||||||
prop.Name,
|
prop.Path,
|
||||||
ColumnCategory.ATTRIBUTE,
|
ColumnCategory.ATTRIBUTE,
|
||||||
GetDataTypeFromTypeName(typeName),
|
GetDataTypeFromTypeName(typeName),
|
||||||
false
|
false
|
||||||
) : prop.GetCustomAttribute<FIELDColumnAttribute>() is not null ? new ColumnInfo(
|
) : declaredType.GetCustomAttribute<FIELDColumnAttribute>() is not null ? new ColumnInfo(
|
||||||
prop.Name,
|
prop.Path,
|
||||||
ColumnCategory.FIELD,
|
ColumnCategory.FIELD,
|
||||||
GetDataTypeFromTypeName(typeName),
|
GetDataTypeFromTypeName(typeName),
|
||||||
false)
|
false)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
//最先检查是不是单侧点模式
|
//最先检查是不是单侧点模式
|
||||||
SingleMeasuringAttribute singleMeasuringAttribute = prop.GetCustomAttribute<SingleMeasuringAttribute>();
|
SingleMeasuringAttribute singleMeasuringAttribute = declaredType.GetCustomAttribute<SingleMeasuringAttribute>();
|
||||||
|
|
||||||
if (singleMeasuringAttribute != null && column == null)
|
if (singleMeasuringAttribute != null && column == null)
|
||||||
{
|
{
|
||||||
@ -679,15 +679,15 @@ namespace JiShe.CollectBus.IoTDB.Provider
|
|||||||
//只有一个Filed字段。
|
//只有一个Filed字段。
|
||||||
//MeasuringName 默认为 SingleMeasuringAttribute.FieldName,以便于在获取对应的Value的时候重置为 Item1 的值。
|
//MeasuringName 默认为 SingleMeasuringAttribute.FieldName,以便于在获取对应的Value的时候重置为 Item1 的值。
|
||||||
|
|
||||||
Type tupleType = prop.PropertyType;
|
//Type tupleType = prop.PropertyType;
|
||||||
Type[] tupleArgs = tupleType.GetGenericArguments();
|
//Type[] tupleArgs = tupleType.GetGenericArguments();
|
||||||
|
|
||||||
column = new ColumnInfo(
|
//column = new ColumnInfo(
|
||||||
singleMeasuringAttribute.FieldName,
|
// singleMeasuringAttribute.FieldName,
|
||||||
ColumnCategory.FIELD,
|
// ColumnCategory.FIELD,
|
||||||
GetDataTypeFromTypeName(tupleArgs[1].Name),
|
// GetDataTypeFromTypeName(tupleArgs[1].Name),
|
||||||
true
|
// true
|
||||||
);
|
//);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (column.HasValue)
|
if (column.HasValue)
|
||||||
|
|||||||
@ -32,11 +32,11 @@ namespace JiShe.CollectBus.Ammeters
|
|||||||
public double Current { get; set; }
|
public double Current { get; set; }
|
||||||
|
|
||||||
[FIELDColumn]
|
[FIELDColumn]
|
||||||
public double Power => Voltage * Current;
|
public double Power { get; set; }
|
||||||
|
|
||||||
[FIELDColumn]
|
[FIELDColumn]
|
||||||
public double? Currentd { get; set; }
|
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>
|
||||||
/// 属性信息集合
|
/// 属性信息集合
|
||||||
/// </summary>
|
/// </summary>
|
||||||
List<PropertyInfo> PropertyInfoList { get; }
|
List<EntityMemberInfo> MemberList { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user