I'm trying to learn and use source generator in C#, but I'm having few issues.
I want to make use of some C# new features, like generic attribute, and use it to generate custom code.
I have for example these attribute:
namespace StrongValues;
[AttributeUsage(AttributeTargets.Struct, Inherited = true, AllowMultiple = false)]
public class StrongValueAttribute<TValue> : StrongValueBaseAttribute
where TValue : IEquatable<TValue>, IComparable<TValue>
;
[AttributeUsage(AttributeTargets.Struct, Inherited = true, AllowMultiple = false)]
public abstract class StrongValueBaseAttribute : Attribute
{
public ConvertOperator ValueToStrongOperator { get; set; } = ConvertOperator.Implicit;
public ConvertOperator StrongToValueOperator { get; set; } = ConvertOperator.Explicit;
public bool UseJsonConverter { get; set; } = true;
public bool UseTypeConverter { get; set; } = true;
}
public enum ConvertOperator
{
_ = 0,
None = _,
Implicit,
Explicit
}
What I want when I use the attribute, like here:
namespace NS
[StrongValue<string>]
public partial struct Email;
is to generate the following:
// Generated
namespace NS;
partial struct Email
{
public string Value { get; init; }
}
I'm trying to make a stripped version from StronglyTypedId
, but I don't know how to detect the attribute properly.
I'm trying first to detect struct types:
var structsToGenerate = context.SyntaxProvider
.ForAttributeWithMetadataName(
Parser.StrongValueAttributeDisplayName,
predicate: (node, _) => node is StructDeclarationSyntax,
transform: Parser.GetStructSemanticTarget)
.Where(static m => m is not null)
;
// Not sure what should be the name here since it's generic.
public const string StrongValueAttributeDisplayName = "StrongValues.StrongValueAttribute`1";
Is this the right way to detect the attribute? How can I get the generic type?
string tValue = null!;
foreach (AttributeData attribute in structSymbol.GetAttributes())
{
if (!(
(attribute.AttributeClass?.Name == "StrongValueAttribute"
|| attribute.AttributeClass?.Name == "StrongValueAttribute`1"
|| attribute.AttributeClass?.Name == "StrongValue"
|| attribute.AttributeClass?.Name == "StrongValue`1")
&& attribute.AttributeClass.ToDisplayString() == StrongValueAttributeDisplayName))
{
// wrong attribute
continue;
}
(var hasMisconfiguredInput, attrProps) = GetConstructorValues(attribute);
if (hasMisconfiguredInput) return null;
tValue = attribute.AttributeClass!.TypeArguments.First().ToDisplayString();
if (tValue is null) return null;
}