[Proposal][net11.0][XSG] Introduce trimming and AOT-safe EventTrigger<T> for XAML Source Generator
- Dominant language
- C#
- Stars
- 23.3k
- Forks
- 2k
- Avg merge
- 1d 15h
- Merged PRs (30d)
- 290
Description
## Summary
Introduce two generic event trigger classes that use compile-time delegates instead of runtime reflection. This enables the XAML Source Generator to produce 100% trimming-safe and AOT-compatible code with zero reflection.
## Motivation
The current `EventTrigger` is incompatible with trimming and AOT:
```csharp
// Current implementation uses reflection
_eventinfo = bindable.GetType().GetRuntimeEvent(Event);
_handlerdelegate = ((EventHandler)OnEventTriggered).Method.CreateDelegate(_eventinfo.EventHandlerType, this);
```
**Problems:**
- ❌ **Trimming unsafe** - event name is a string, trimmer can't trace it
- ❌ **AOT incompatible** - `CreateDelegate()` requires runtime code generation
- ❌ **No compile-time validation** - typos fail at runtime
## Proposed Solution
Two generic classes that accept add/remove delegates - completely reflection-free:
```csharp
// For events using EventHandler (Entry.Focused, Entry.TextChanged, etc.)
new EventTrigger(
static (e, h) => e.Focused += h,
static (e, h) => e.Focused -= h);
// For events using plain EventHandler (Button.Clicked, etc.)
new EventTrigger(
static (b, h) => b.Clicked += h,
static (b, h) => b.Clicked -= h);
```
**Prototype:** https://gist.github.com/simonrozsival/5b27ff816b2a24f1dc5466bf55a2a57a
## Why Two Classes?
`EventHandler` and `EventHandler` are incompatible delegate types in .NET - they cannot be unified in a single generic class without reflection. By having two classes, each can use direct method assignment:
```csharp
_handler = OnEventTriggered; // ✅ Direct assignment, no reflection!
```
## Comparison
| Aspect | `EventTrigger` (current) | `EventTrigger` (proposed) |
|--------|--------------------------|------------------------------|
| **Trimming** | ❌ Unsafe | ✅ Safe |
| **AOT** | ❌ Requires reflection | ✅ 100% reflection-free |
| **Compile-time validation** | ❌ Runtime errors | ✅ Build errors |
| **Handler creation** | `Delegate.CreateDelegate()` | Direct method assignment |
## Implementation Plan
1. Add `EventTrigger` and `EventTrigger` classes
2. Update XSG to emit appropriate class based on event handler type
3. Keep existing `EventTrigger` with `[RequiresUnreferencedCode]` for compatibility
## Open Questions
1. Should we add a feature switch to control XSG behavior?
2. Public API or internal (XSG-only)?
3. Naming preference?
Contributor guide
Research direction
Start by reviewing the linked prototype and the current EventTrigger implementation, then trace how the XAML Source Generator emits event triggers. Done means the two generic trigger variants are reflection-free and trimming/AOT-safe, the generator selects the appropriate variant, and the existing compatibility path remains annotated as planned.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 30/100