Created a builder for attributes in code generator

This commit is contained in:
Samuele Lorefice
2025-02-25 16:32:38 +01:00
parent 23cec0bd0f
commit 91b74a24dd
2 changed files with 126 additions and 255 deletions

View File

@@ -0,0 +1,106 @@
using System;
using System.CodeDom;
using System.Collections.Generic;
namespace CodeGenerator {
public class AttributeBuilder {
private static AttributeBuilder _instance;
public static AttributeBuilder Instance => _instance ??= new();
private CodeTypeDeclaration _attrDecl = new();
private List<(Type, string)> _fields = new();
private List<(Type, string, string)> _properties = new();
public AttributeBuilder New() {
_attrDecl.IsClass = true;
_attrDecl.Attributes = MemberAttributes.Public;
_attrDecl.BaseTypes.Add(typeof(Attribute));
return this;
}
public AttributeBuilder New(string name) {
New();
_attrDecl.Name = name;
return this;
}
public AttributeBuilder SetAttributeUsage(CodeAttributeArgument usageArgs) {
var attrUsage = new CodeAttributeDeclaration() {
Name = nameof(AttributeUsageAttribute),
Arguments = { usageArgs }
};
_attrDecl.CustomAttributes.Add(attrUsage);
return this;
}
// ReSharper disable always BitwiseOperatorOnEnumWithoutFlags
public AttributeBuilder AddField<T>(string name,
MemberAttributes attributes = MemberAttributes.Private | MemberAttributes.Final) =>
AddField(typeof(T), name, attributes);
public AttributeBuilder AddField(string type, string name,
MemberAttributes attributes = MemberAttributes.Private | MemberAttributes.Final) =>
AddField(Type.GetType(type), name, attributes);
public AttributeBuilder AddField(Type type, string name,
MemberAttributes attributes = MemberAttributes.Private | MemberAttributes.Final) {
var field = new CodeMemberField(type, name);
field.Attributes = attributes;
_attrDecl.Members.Add(field);
_fields.Add((type, name));
return this;
}
public AttributeBuilder AddAutoProperty(Type type, string name, MemberAttributes attributes = MemberAttributes.Public, bool get = true, bool set = true) {
AddField(type, $"_{name}", MemberAttributes.Private);
return AddProperty(type, name, $"_{name}", attributes, get, set);
}
public AttributeBuilder AddProperty(Type type, string name, string backingPropertyName,
MemberAttributes attributes = MemberAttributes.Public, bool get = true, bool set = true) {
var prop = new CodeMemberProperty {
Name = name,
Type = new (type),
Attributes = attributes,
HasGet = get,
HasSet = set
};
if (get) {
prop.GetStatements.Add(
new CodeMethodReturnStatement(
new CodeFieldReferenceExpression(
new CodeThisReferenceExpression(), backingPropertyName)));
}
if (set) {
prop.SetStatements.Add(
new CodeAssignStatement(
new CodeFieldReferenceExpression(
new CodeThisReferenceExpression(), backingPropertyName),
new CodePropertySetValueReferenceExpression()));
}
_properties.Add((type, name, backingPropertyName));
_attrDecl.Members.Add(prop);
return this;
}
public AttributeBuilder AddPropertiesConstructor() {
var ctor = new CodeConstructor { Attributes = MemberAttributes.Public };
_attrDecl.Members.Add(ctor);
_properties.ForEach(property => {
ctor.Parameters.Add(new (property.Item1, property.Item2));
ctor.Statements.Add(
new CodeAssignStatement(
new CodeFieldReferenceExpression(
new CodeThisReferenceExpression(), property.Item3), new CodeVariableReferenceExpression(property.Item2)));
});
return this;
}
public CodeTypeDeclaration Build() => _attrDecl;
}
}