Background and motivation
Reflectify contains no trimming or AOT annotations at all: no [DynamicallyAccessedMembers], no [RequiresUnreferencedCode], no [UnconditionalSuppressMessage].
This matters more for Reflectify than for a normal library, because of how it is delivered. It is a content-only package: the source is compiled directly into the consumer's assembly. So when a consumer publishes with PublishTrimmed or NativeAOT, the trim analyzer walks Reflectify's code as if the consumer wrote it, and reports warnings against the consumer's own project. The consumer cannot suppress them at the package boundary and cannot fix them without editing generated source.
Every hierarchy walk in Reflector is a warning site. For example:
var allProperties = typeToReflect.GetProperties(flags);
and
return type
.GetMethods(flags)
.SingleOrDefault(m => m.Name == methodName && HasSameParameters(parameterTypes, m));
Both take a Type with no annotation, so the analyzer cannot prove the members survive trimming and emits IL2070-class warnings. Same for GetMethod("Equals", ...) in OverridesEquals, the "<Clone>$" and "PrintMembers" lookups in the record detection, and every GetCustomAttributes call.
Annotating the API would let consumers who are trim-clean stay trim-clean. Because the parameters are Type, the annotations mostly land on the public extension methods and flow inward.
PolySharp is already a dependency and can generate DynamicallyAccessedMembersAttribute, RequiresUnreferencedCodeAttribute and UnconditionalSuppressMessageAttribute for the older targets, so the multi-targeting story is already solved.
Alternative Concerns
- Annotate everything with
[DynamicallyAccessedMembers]. The correct fix, and it preserves trimming for consumers. The cost is that the annotations are viral: a caller passing an unannotated Type just moves the warning up one level. That is arguably fine, since it moves the warning to where the type is actually known.
- Mark the reflection-heavy methods
[RequiresUnreferencedCode] instead. Much less work and honest about what the code does, but it makes the whole library unusable warning-free in trimmed apps, which is a worse outcome than annotating.
- Do nothing and document that Reflectify is not trim-safe. Cheapest, and defensible for a reflection library, but it effectively rules out NativeAOT consumers, which is a growing constituency.
- Add a trimming test. Whatever is chosen, a small
PublishTrimmed / PublishAot smoke project in the build would prevent regressions and prove the annotations actually work. That could be a first step on its own, since it would quantify how many warnings there are today.
Worth noting that some methods, such as the record detection heuristics, genuinely cannot be made trim-safe, since they look up members by string name that the compiler generates. Those are honest [RequiresUnreferencedCode] or suppression candidates.
Are you willing help with a pull-request?
No
Background and motivation
Reflectify contains no trimming or AOT annotations at all: no
[DynamicallyAccessedMembers], no[RequiresUnreferencedCode], no[UnconditionalSuppressMessage].This matters more for Reflectify than for a normal library, because of how it is delivered. It is a content-only package: the source is compiled directly into the consumer's assembly. So when a consumer publishes with
PublishTrimmedor NativeAOT, the trim analyzer walks Reflectify's code as if the consumer wrote it, and reports warnings against the consumer's own project. The consumer cannot suppress them at the package boundary and cannot fix them without editing generated source.Every hierarchy walk in
Reflectoris a warning site. For example:and
Both take a
Typewith no annotation, so the analyzer cannot prove the members survive trimming and emits IL2070-class warnings. Same forGetMethod("Equals", ...)inOverridesEquals, the"<Clone>$"and"PrintMembers"lookups in the record detection, and everyGetCustomAttributescall.Annotating the API would let consumers who are trim-clean stay trim-clean. Because the parameters are
Type, the annotations mostly land on the public extension methods and flow inward.PolySharpis already a dependency and can generateDynamicallyAccessedMembersAttribute,RequiresUnreferencedCodeAttributeandUnconditionalSuppressMessageAttributefor the older targets, so the multi-targeting story is already solved.Alternative Concerns
[DynamicallyAccessedMembers]. The correct fix, and it preserves trimming for consumers. The cost is that the annotations are viral: a caller passing an unannotatedTypejust moves the warning up one level. That is arguably fine, since it moves the warning to where the type is actually known.[RequiresUnreferencedCode]instead. Much less work and honest about what the code does, but it makes the whole library unusable warning-free in trimmed apps, which is a worse outcome than annotating.PublishTrimmed/PublishAotsmoke project in the build would prevent regressions and prove the annotations actually work. That could be a first step on its own, since it would quantify how many warnings there are today.Worth noting that some methods, such as the record detection heuristics, genuinely cannot be made trim-safe, since they look up members by string name that the compiler generates. Those are honest
[RequiresUnreferencedCode]or suppression candidates.Are you willing help with a pull-request?
No