dennisdoomen / dennisdoomen/reflectify
[Feature]: Ship an analyzer that validates member-name strings passed to FindMethod, FindProperty and FindField
- Dominant language
- C#
- Stars
- 80
- Forks
- 6
- Avg merge
- 1d 12m
- Merged PRs (30d)
- 11
Description
### Background and motivation
Several Reflectify APIs take member names as strings and return `null` when nothing matches:
```csharp
public static MethodInfo FindMethod(this Type type, string methodName, MemberKind kind, params Type[] parameterTypes)
public static PropertyInfo FindProperty(this Type type, string propertyName, MemberKind memberVisibility)
public static FieldInfo FindField(this Type type, string fieldName, MemberKind memberVisibility)
public static bool HasMethod(this Type type, string methodName, MemberKind memberKind, params Type[] parameterTypes)
```
When the string is a literal and the type is statically known, which is the overwhelmingly common case, a typo or a rename produces no compiler error. `FindProperty` silently returns `null`, and the failure shows up much later as a `NullReferenceException` far from the cause. A rename refactoring in the IDE will not update these strings either, so they rot quietly.
An analyzer could resolve these at compile time and report an obvious diagnostic: "type `Order` has no public property named `Naem`". The information needed is all available to Roslyn: the receiver type from `typeof(X)`, the literal string, and the `MemberKind` flags from the constant argument.
There is precedent worth borrowing from: `RandomAccess`-style analyzers, the `nameof`-preferring analyzers in ASP.NET Core, and the argument analyzers shipped with several assertion libraries. The repo already has an analyzer-friendly setup, with a `.editorconfig`, DotSettings and existing `AV####` suppressions in the source.
A second, more ambitious step would be a source generator that resolves the lookup at build time and emits direct member access, removing the runtime reflection entirely for the static cases. That would help the trimming and AOT story considerably, but it is a much larger project and should be judged separately.
### Alternative Concerns
- **Analyzer only, no generator.** Far smaller scope, catches the actual bug people hit, and does not change runtime behaviour at all. This is the version most likely to be worth building.
- **Offer `nameof`-friendly overloads instead.** Callers can already write `FindProperty(nameof(Order.Name), ...)`, which is compile-checked and rename-safe today. Documenting that in the README is nearly free and gets most of the benefit with zero new machinery. Arguably this should be tried first.
- **Add expression-based overloads**, e.g. `FindProperty(o => o.Name)`. Fully type-safe, no analyzer needed, but it allocates an expression tree per call and does not work for internal or explicitly implemented members, which are precisely the cases Reflectify exists to handle.
- **Do nothing.** Defensible: the library is intentionally small and dependency-free, and shipping an analyzer alongside a content-only package raises packaging questions of its own, since the analyzer would need to be a separate package or an extra asset in the same one.
Worth noting an interaction with the delivery model: because Reflectify compiles into the consumer's assembly, an analyzer would need to detect Reflectify's methods structurally (by namespace and signature) rather than by assembly identity.
### Are you willing help with a pull-request?
No
Contributor guide
Research direction
Start by reviewing the repository's .editorconfig, DotSettings, and existing AV#### suppressions to understand the analyzer-friendly setup. Resolve the open scope questions first: analyzer-only versus nameof documentation, packaging, structural method detection, and whether the source-generator idea is excluded. Done should mean a defined analyzer design that reports invalid literal member names without changing runtime behavior.
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
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100