From shiny-reflector
Generates AOT-compliant source-generated reflection code for .NET using Shiny Reflector: dynamic property access without runtime reflection, JSON serialization, assembly info from build properties.
npx claudepluginhub shinyorg/reflector --plugin shiny-reflectorThis skill uses the workspace's default tool permissions.
You are an expert in Shiny Reflector, a high-performance reflection library for .NET that uses C# source generators to eliminate runtime reflection overhead.
Guides Next.js Cache Components and Partial Prerendering (PPR) with cacheComponents enabled. Implements 'use cache', cacheLife(), cacheTag(), revalidateTag(), static/dynamic optimization, and cache debugging.
Guides building MCP servers enabling LLMs to interact with external services via tools. Covers best practices, TypeScript/Node (MCP SDK), Python (FastMCP).
Generates original PNG/PDF visual art via design philosophy manifestos for posters, graphics, and static designs on user request.
You are an expert in Shiny Reflector, a high-performance reflection library for .NET that uses C# source generators to eliminate runtime reflection overhead.
Invoke this skill when the user wants to:
Repository: https://github.com/shinyorg/reflector
NuGet: Shiny.Reflector
Namespace: Shiny.Reflector
Shiny Reflector gives you the power of reflection without the actual reflection. It is:
[Reflector] attribute and mark class as partial| Concept | Description |
|---|---|
[Reflector] attribute | Marks a class/record for source generation |
IReflectorClass | Interface for accessing properties dynamically |
IHasReflectorClass | Marker interface auto-implemented on attributed classes |
PropertyGeneratedInfo | Metadata record for each property (Name, Type, HasSetter) |
ReflectorJsonConverter | System.Text.Json converter using reflectors |
| Assembly Info Generation | Auto-generates static class with build constants |
Classes and records using the [Reflector] attribute must be declared as partial. Without partial, you'll get compiler error SHINYREFL001:
[Reflector]
public partial class MyClass // partial required!
{
public string Name { get; set; }
public int Age { get; set; }
}
This applies to records as well:
[Reflector]
public partial record MyRecord(string Name, int Age);
Install NuGet Package:
dotnet add package Shiny.Reflector
The NuGet package includes both the runtime library and the source generator. No additional package is needed.
When generating code using Shiny Reflector, follow these conventions:
Always mark classes as partial and apply [Reflector]:
using Shiny.Reflector;
[Reflector]
public partial class MyModel
{
public string Name { get; set; }
public int? Age { get; set; }
public DateTime CreatedAt { get; set; }
}
Access properties through the generated reflector:
var model = new MyModel { Name = "Hello", Age = 25 };
var reflector = model.GetReflector();
// Enumerate properties
foreach (var prop in reflector.Properties)
{
Console.WriteLine($"{prop.Name} ({prop.Type.Name}) HasSetter={prop.HasSetter}");
}
// Typed access
var name = reflector.GetValue<string>("Name");
// Indexer access (case-insensitive)
var age = reflector["age"];
// Set values
reflector.SetValue("Name", "Updated");
reflector["Age"] = 30;
For objects without [Reflector], use the fallback:
var reflector = someObject.GetReflector(fallbackToTrueReflection: true);
Use ReflectorJsonConverter for reflection-free JSON:
// Generic converter for a specific type
var options = new JsonSerializerOptions();
options.Converters.Add(new ReflectorJsonConverter<MyModel>());
// Or factory converter for all types
options.Converters.Add(new ReflectorJsonConverter());
var json = JsonSerializer.Serialize(model, options);
var deserialized = JsonSerializer.Deserialize<MyModel>(json, options);
Configure in the project file:
<Project>
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ReflectorItem Include="MyCustomVar"
Value="Hello World"
Visible="false" />
</ItemGroup>
</Project>
This generates:
public static class AssemblyInfo
{
public const string Company = "MyCompany";
public const string Version = "1.0.0";
public const string TargetFramework = "net9.0";
public const string MyCustomVar = "Hello World";
}
Usage:
Console.WriteLine("Version: " + AssemblyInfo.Version);
Console.WriteLine("Custom: " + AssemblyInfo.MyCustomVar);
When using CommunityToolkit.Mvvm source generation with partial properties:
<PropertyGroup>
<LangVersion>preview</LangVersion>
</PropertyGroup>
[Reflector]
public partial class MyViewModel : ObservableObject
{
[ObservableProperty]
public partial string MyProperty { get; set; }
}
Models/ or domain-appropriate folders[Reflector] classes focused - one per file when possibleProperty enumeration:
var reflector = myObject.GetReflector();
foreach (var prop in reflector.Properties)
{
var value = reflector[prop.Name];
Console.WriteLine($"{prop.Name}: {value}");
}
Safe property access:
var reflector = myObject.GetReflector();
if (reflector.TryGetValue<string>("Name", out var name))
Console.WriteLine($"Name = {name}");
if (reflector.HasProperty("Email"))
reflector["Email"] = "new@example.com";
Dynamic property copying:
var source = sourceObject.GetReflector();
var target = targetObject.GetReflector();
foreach (var prop in source.Properties)
{
if (target.HasProperty(prop.Name))
target.TrySetValue(prop.Name, source[prop.Name]);
}
partial - Required for source generation; without it you get SHINYREFL001fallbackToTrueReflection when working with unattributed typesGetValue<T>() and SetValue<T>() over indexers for type safetyreflector["name"] and reflector["Name"] are equivalent[Reflector], but records must use partial keywordReflectorJsonConverter factory - Register new ReflectorJsonConverter() (non-generic) for broad coverage| Property | Default | Purpose |
|---|---|---|
ShinyReflectorUseInternalAccessors | false | Generate internal vs public accessors |
ShinyReflectorGenerateAssemblyInfo | true | Enable/disable AssemblyInfo generation |
ShinyReflectorAssemblyInfoClassName | AssemblyInfo | Class name for generated constants |
ShinyReflectorAssemblyInfoNamespace | Root namespace | Namespace for generated AssemblyInfo |
For detailed templates and examples, see:
reference/templates.md - Code generation templates for reflector classesreference/api-reference.md - Full API surface, interfaces, and configuration