Skip to content

[Feature]: Ship an analyzer that validates member-name strings passed to FindMethod, FindProperty and FindField #168

Description

@dennisdoomen

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

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions