Background and motivation
Several Reflectify APIs take member names as strings and return null when nothing matches:
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<Order>(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
Background and motivation
Several Reflectify APIs take member names as strings and return
nullwhen nothing matches: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.
FindPropertysilently returnsnull, and the failure shows up much later as aNullReferenceExceptionfar 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
Orderhas no public property namedNaem". The information needed is all available to Roslyn: the receiver type fromtypeof(X), the literal string, and theMemberKindflags from the constant argument.There is precedent worth borrowing from:
RandomAccess-style analyzers, thenameof-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 existingAV####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
nameof-friendly overloads instead. Callers can already writeFindProperty(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.FindProperty<Order>(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.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