Start here. This is the direct spoken answer to practice first.
Why this question matters
Reflection can remove repetitive registration code, but it creates a runtime dependency that the compiler and linker may not be able to see. Deployment mode turns that convenience into a correctness boundary.
Attributes attach metadata to program elements; reflection reads that metadata and inspects types or members at runtime. This can support plugin discovery, serialization, validation, or mapping without hard-coded registration. The cost is more runtime work, weaker compile-time guarantees, and failures that appear only when a type or constructor is missing. With trimming or Native AOT, code reached only through reflection may be removed because static analysis cannot prove it is needed.