Guide for implementing Smart Enums, Value Objects, and Discriminated Unions in .NET using Roslyn Source Generators with zero-hallucination verification practices
This skill provides comprehensive guidance for working with the Thinktecture.Runtime.Extensions library, which implements Smart Enums, Value Objects, and Discriminated Unions in .NET through Roslyn Source Generators.
Thinktecture.Runtime.Extensions is a .NET library that uses source generators to create boilerplate code for type-safe domain modeling patterns. It includes 6 source generators and 2 analyzers to validate usage and generate implementations.
**Keyless Smart Enums** (`[SmartEnum]`):
**Keyed Smart Enums** (`[SmartEnum<TKey>]`):
**Simple Value Objects** (`[ValueObject<TKey>]`):
**Complex Value Objects** (`[ComplexValueObject]`):
**Ad-hoc Unions** (`[Union<T1, T2>]` or `[AdHocUnion(typeof(T1), typeof(T2))]`):
**Regular Unions** (`[Union]`):
When working with external libraries or .NET APIs:
1. **Never guess or assume API behavior** - Do not rely on memory or general knowledge
2. **Verify using Context7 MCP** when uncertain about external APIs:
- Use `mcp__context7__resolve-library-id` to find library ID
- Use `mcp__context7__get-library-docs` to retrieve documentation
3. **Verification over speed** - Better to take time to verify than introduce bugs
4. **Explicitly communicate uncertainty** - State when verification is needed
5. **Use codebase as authoritative source** for internal library code
**Always delegate to subagents when:**
**Do NOT delegate simple tasks:**
- `ValidateFactoryArguments` returns `ValidationError` for better framework integration
- `ValidateConstructorArguments` can only throw exceptions
1. **Types must be `partial`** - All Smart Enums, Value Objects, and Unions require the `partial` keyword
2. **String-based keys/members** - Always explicitly specify equality comparer (e.g., `[KeyMemberEqualityComparer<MyType, string, StringComparer>]`)
3. **Immutability** - All members should be readonly (fields) or have no setter/private init (properties)
4. **Constructors** - Keep constructors private to enforce use of factory methods
5. **Smart Enum items** - Must be public static readonly fields
```bash
dotnet build # Build solution
dotnet restore # Restore packages
dotnet test # Run all tests
```
Generated types implement `IMetadataOwner` interface with runtime metadata that enables:
The `MetadataLookup` class provides cached metadata discovery via reflection. Object factories have priority over key-based metadata for conversion scenarios.
1. **"Type must be partial"**: Add `partial` keyword to class/struct declaration
2. **"String-based value object needs equality comparer"**: Add `[KeyMemberEqualityComparer<MyType, string, StringComparer>]`
3. **"Smart enum has no items"**: Ensure items are public static readonly fields of the enum type
4. **Serialization not working**: Reference integration package or manually register converters
5. **EF Core not converting**: Call `.UseThinktectureValueConverters()` on DbContextOptionsBuilder
6. **ISpanParsable not available**: Requires NET9+; ensure project targets `net9.0` or later
1. Always use `partial` keyword for generated types
2. Explicitly specify equality comparers for string-based keys
3. Prefer `ValidateFactoryArguments` over `ValidateConstructorArguments`
4. Keep all members immutable (readonly fields or init-only properties)
5. Keep constructors private, enforce factory method usage
6. Verify external API behavior using Context7 MCP - never guess
7. Delegate complex multi-step tasks to specialized subagents
8. Pass appropriate `IFormatProvider` when parsing/formatting culture-sensitive types
9. Use unchecked arithmetic context for arithmetic operators
Leave a review
No reviews yet. Be the first to review this skill!
# Download SKILL.md from killerskills.ai/api/skills/thinktecture-runtime-extensions/raw