Генерировать полное свойство от простого свойства с генераторомC#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Генерировать полное свойство от простого свойства с генератором

Сообщение Anonymous »

Я пытаюсь взять класс, подобный ниже, с атрибутом [AutoSave] :

Код: Выделить всё

[AutoSave]
public partial class GeneratedConfig : NotifiyingJsonSettings, IVersionable
{
[EnforcedVersion("1.0.0.0")]
public Version Version { get; set; } = new Version(1, 0, 0, 0);
public override string FileName { get; set; } = $"{AppContext.BaseDirectory}GeneratedConfig.json";
public virtual string TestString { get; set; }
public virtual bool TestBool { get; set; }
}
, который должен генерировать следующий класс (и мой генератор генерирует следующий класс, и я могу видеть сгенерированный класс в зависимости -> Analyzer -> libname.autosavegenerator ):

Код: Выделить всё

public partial class GeneratedConfig : NotifiyingJsonSettings, IVersionable
{
private System.Version version = new Version(1, 0, 0, 0);

[EnforcedVersion("1.0.0.0")]
public System.Version Version
{
get => version;
set
{
version = value;
OnPropertyChanged(nameof(Version));
Save();
}
}

private string fileName = $"{AppContext.BaseDirectory}NativeConfig.json";

public override string FileName
{
get => fileName;
set
{
if (fileName != value)
{
fileName = value;
OnPropertyChanged(nameof(FileName));
Save();
}
}
}

private string _testString;

public string TestString
{
get => _testString;
set
{
_testString = value;
OnPropertyChanged(nameof(TestString));
Save();
}
}

private bool _testBool;

public bool TestBool
{
get => _testBool;
set
{
_testBool = value;
OnPropertyChanged(nameof(TestBool));
Save();
}
}
}
< /code>
Но когда я составляю свое приложение, я получаю некоторые ошибки - например: < /p>

Тип 'GeneratedConfig' уже содержит определение для «filename»

type 'GeneratedCyg' уже содержит определение для «br />
'Testbool'

type 'GeneratedConfig' уже содержит определение для 'teststring' < /p>
< /blockquote>
Я использую этот код генератора: < /p>
[Generator]
public class AutoSaveGenerator : IIncrementalGenerator
{
public void Initialize(IncrementalGeneratorInitializationContext context)
{
var classesWithAttribute = context.SyntaxProvider
.CreateSyntaxProvider(
predicate: static (s, _) => s is ClassDeclarationSyntax cds && cds.AttributeLists.Count > 0,
transform: static (ctx, _) => GetClassWithAttribute(ctx))
.Where(static classWithAttribute => classWithAttribute is not null);

context.RegisterSourceOutput(classesWithAttribute, (context, classInfo) =>
{
var generatedCode = GenerateClassWithAutoSave(classInfo);
context.AddSource($"{classInfo!.ClassName}_AutoSave.g.cs", SourceText.From(generatedCode, Encoding.UTF8));
});
}

private static ClassInfo? GetClassWithAttribute(GeneratorSyntaxContext context)
{
var classDeclaration = (ClassDeclarationSyntax)context.Node;
var semanticModel = context.SemanticModel;

var classSymbol = semanticModel.GetDeclaredSymbol(classDeclaration) as INamedTypeSymbol;

if (classSymbol == null)
return null;

bool hasTargetAttribute = classSymbol.GetAttributes()
.Any(attr => attr.AttributeClass?.Name == "AutoSaveAttribute" ||
attr.AttributeClass?.ToDisplayString() == "AutoSave.AutoSaveAttribute");

if (!hasTargetAttribute)
return null;

var accessibility = classSymbol.DeclaredAccessibility.ToString().ToLower();

// Collect property information
var properties = classDeclaration.Members
.OfType
()
.Select(p =>  new PropertyInfo
{
Name = p.Identifier.Text,
Type = semanticModel.GetTypeInfo(p.Type).Type?.ToDisplayString() ?? "object",
IsVirtual = p.Modifiers.Any(SyntaxKind.VirtualKeyword),
IsOverride = p.Modifiers.Any(SyntaxKind.OverrideKeyword),
DefaultValue = p.Initializer?.Value.ToString(),
Attributes = p.AttributeLists
.SelectMany(a => a.Attributes)
.Select(a => a.ToString())
.ToList()
})
.ToList();

var baseTypes = GetBaseTypes(classSymbol);

// Return class info with properties and base types
return new ClassInfo
{
Accessibility = accessibility,
ClassName = classSymbol.Name,
Namespace = classSymbol.ContainingNamespace.ToDisplayString(),
Properties = properties,
BaseTypes = baseTypes
};
}

private static List GetBaseTypes(INamedTypeSymbol classSymbol)
{
var baseTypes = new List();
var currentBase = classSymbol.BaseType;

while (currentBase != null && currentBase.ToDisplayString() != "object")
{
baseTypes.Add(currentBase.ToDisplayString());
currentBase = currentBase.BaseType;
}

foreach (var iface in classSymbol.Interfaces)
{
baseTypes.Add(iface.ToDisplayString());
}

return baseTypes;
}

private static string GenerateClassWithAutoSave(ClassInfo classInfo)
{
var sb = new StringBuilder();

// Add required usings
sb.AppendLine("using Nucs.JsonSettings.Modulation;");
sb.AppendLine();

// File-scoped namespace
sb.AppendLine($"namespace {classInfo.Namespace};");
sb.AppendLine();

// Start class declaration with base types if any
var baseTypeList = classInfo.BaseTypes;
baseTypeList.Remove("Nucs.JsonSettings.JsonSettings");
baseTypeList.Remove("JsonSettings");
var baseTypesString = classInfo.BaseTypes.Count > 0 ? " : " + string.Join(", ", baseTypeList) : string.Empty;
sb.AppendLine($"{classInfo.Accessibility} partial class {classInfo.ClassName}{baseTypesString}");
sb.AppendLine("{");

foreach (var prop in classInfo.Properties)
{
string fieldName = char.ToLower(prop.Name[0]) + prop.Name.Substring(1);

// Generate private field with default value if it exists
sb.AppendLine($"    private {prop.Type} {fieldName}" +
(prop.DefaultValue != null ? $" = {prop.DefaultValue};" : ";"));

// Add attributes if any
foreach (var attribute in prop.Attributes)
{
sb.AppendLine($"    [{attribute}]");
}

// Generate property
sb.AppendLine($"    {(prop.IsOverride ? "public override" : "public")}" +
$" {prop.Type} {prop.Name}");
sb.AppendLine("    {");
sb.AppendLine($"        get => {fieldName};");
sb.AppendLine("        set");
sb.AppendLine("        {");
sb.AppendLine($"            if ({fieldName} != value)"); // Add the condition here
sb.AppendLine("            {");
sb.AppendLine($"                {fieldName} = value;");
sb.AppendLine($"                OnPropertyChanged(nameof({prop.Name}));"); // Ensure OnPropertyChanged() is called
sb.AppendLine("                Save();"); // Call Save() only if value changed
sb.AppendLine("            }");
sb.AppendLine("        }");
sb.AppendLine("    }");
}

sb.AppendLine("}");

return sb.ToString();
}

private class ClassInfo
{
public string Accessibility { get; set; } = "public";
public string ClassName { get; set; }
public string Namespace { get; set; }
public List Properties { get; set;  } = new();
public List BaseTypes { get; set; } = new();
}

private class PropertyInfo
{
public string Name { get; set; }
public string Type { get; set; }
public bool IsVirtual { get; set; }
public bool IsOverride { get; set; }
public string? DefaultValue { get; set; }
public List Attributes { get; set; } = new();
}
}
Как я могу исправить это дубликатное свойство?


Подробнее здесь: https://stackoverflow.com/questions/791 ... -generator
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C#»