Documentation Index
Fetch the complete documentation index at: https://ancplua.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
Extension methods for extracting constructor arguments and named arguments from AttributeData.
The Problem
Extracting attribute values requires verbose loops and null checks:
// BAD: Verbose and error-prone
string? displayName = null;
foreach (var attr in symbol.GetAttributes())
{
if (attr.AttributeClass?.ToDisplayString() == "System.ComponentModel.DataAnnotations.DisplayAttribute")
{
foreach (var namedArg in attr.NamedArguments)
{
if (namedArg.Key == "Name" && namedArg.Value.Value is string name)
{
displayName = name;
break;
}
}
}
}
The Solution
// GOOD: Clean and type-safe
var displayName = symbol.GetAttributeNamedArgument<string>(
"System.ComponentModel.DataAnnotations.DisplayAttribute", "Name");
Constructor Arguments
Extract positional arguments from attribute constructors:
// [JsonDerivedType(typeof(DerivedClass), "discriminator")]
var derivedType = attribute.GetConstructorArgument<INamedTypeSymbol>(0);
var discriminator = attribute.GetConstructorArgument<string>(1);
// Try-pattern for conditional extraction
if (attribute.TryGetConstructorArgument<int>(0, out var index))
{
// Use index
}
// Get argument count
int count = attribute.GetConstructorArgumentCount();
Named Arguments
Extract named property/field arguments:
// [Display(Name = "User Name", Order = 1)]
var displayName = attribute.GetNamedArgument<string>("Name");
var order = attribute.GetNamedArgument<int>("Order");
// Try-pattern
if (attribute.TryGetNamedArgument<bool>("IsRequired", out var isRequired) && isRequired)
{
// Handle required field
}
// Check existence
if (attribute.HasNamedArgument("Name"))
{
// Name was explicitly set
}
// Get all argument names
foreach (var name in attribute.GetNamedArgumentNames())
{
Console.WriteLine(name);
}
Symbol Convenience Methods
Get attribute values directly from symbols:
// Constructor argument from symbol
var derivedType = type.GetAttributeConstructorArgument<INamedTypeSymbol>(
"System.Text.Json.Serialization.JsonDerivedTypeAttribute", 0);
// Named argument from symbol
var displayName = property.GetAttributeNamedArgument<string>(
"System.ComponentModel.DataAnnotations.DisplayAttribute", "Name") ?? property.Name;
// Using type symbol instead of string
var attrType = compilation.GetTypeByMetadataName("MyNamespace.MyAttribute");
var value = symbol.GetAttributeNamedArgument<string>(attrType, "PropertyName");
// Try-pattern from symbol
if (symbol.TryGetAttributeConstructorArgument<int>("MyAttribute", 0, out var priority))
{
// Use priority
}
Array Arguments
Extract array-typed arguments:
// [MyAttribute(new[] { "a", "b", "c" })]
ImmutableArray<string> values = attribute.GetConstructorArgumentArray<string>(0);
// [MyAttribute(Roles = new[] { Role.Admin, Role.User })]
ImmutableArray<int> roles = attribute.GetNamedArgumentArray<int>("Roles");
Common Patterns
Get Display Name
// Returns DisplayAttribute.Name or falls back to symbol name
var displayName = property.GetDisplayName();
// With pre-resolved type symbol (better performance in loops)
var displayAttr = compilation.GetTypeByMetadataName(
"System.ComponentModel.DataAnnotations.DisplayAttribute");
var displayName = property.GetDisplayName(displayAttr);
Get JSON Derived Types
// Extract all types from [JsonDerivedType] attributes
var jsonDerivedType = compilation.GetTypeByMetadataName(
"System.Text.Json.Serialization.JsonDerivedTypeAttribute");
ImmutableArray<INamedTypeSymbol>? derivedTypes = baseType.GetJsonDerivedTypes(jsonDerivedType);
if (derivedTypes.HasValue)
{
foreach (var derivedType in derivedTypes.Value)
{
// Process each derived type
}
}
API Reference
| Method | Description |
|---|
GetConstructorArgument<T>(index) | Gets constructor argument at index |
TryGetConstructorArgument<T>(index, out value) | Try-pattern for constructor argument |
GetConstructorArgumentCount() | Returns number of constructor arguments |
GetNamedArgument<T>(name) | Gets named argument by name |
TryGetNamedArgument<T>(name, out value) | Try-pattern for named argument |
HasNamedArgument(name) | Checks if named argument exists |
GetNamedArgumentNames() | Enumerates all named argument names |
GetConstructorArgumentArray<T>(index) | Gets array constructor argument |
GetNamedArgumentArray<T>(name) | Gets array named argument |
GetAttributeConstructorArgument<T>(symbol, attrName, index) | Gets constructor arg from symbol’s attribute |
GetAttributeNamedArgument<T>(symbol, attrName, argName) | Gets named arg from symbol’s attribute |
GetDisplayName(symbol) | Gets DisplayAttribute.Name or symbol name |
GetJsonDerivedTypes(type, attrType) | Gets all JsonDerivedType type arguments |