About • How To Use • Download • Contributors • Versioning • Credits • Related • License
Reflectify offers a bunch of extension methods to provide information such as the properties or fields a type exposes and metadata about those members, and many other details about classes, records and interfaces. It supports all major .NET versions and even understands explicitly implemented properties or properties coming from default interface implementations, a C# 8 feature.
Nothing really, but it offers that functionality through a content-only NuGet package that relies on C# 12. In other words, you can use this package in your own packages, without the need to tie yourself to the Reflectify package. Oh, and it's used by an open-source project with over 400 million downloads.
My name is Dennis Doomen and I'm a Microsoft MVP and Principal Consultant at Aviva Solutions with 28 years of experience under my belt. As a software architect and/or lead developer, I specialize in designing full-stack enterprise solutions based on .NET as well as providing coaching on all aspects of designing, building, deploying and maintaining software systems. I'm the author of Fluent Assertions, a popular .NET assertion library, Liquid Projections, a set of libraries for building Event Sourcing projections and I've been maintaining coding guidelines for C# since 2001.
Contact me through Email, BlueSky, Twitter/X or Mastadon
Simple, to get the properties of a type, add the Reflectify NuGet package to a project that targets at least C# 12 and use
using Reflectify;
var properties = typeof(SuperClass).GetProperties(
MemberKind.Public | MemberKind.ExplicitlyImplemented | MemberKind.DefaultInterfaceProperties);You can take any of the options Public, Internal, Protected, Private, Static, ExplictlyImplemented and DefaultInterfaceProperties.
If you need the fields, use GetFields (which obviously cannot be explicitly implemented, nor be part of interfaces),
and if you need the members, use GetMembers. You can also request individual members by name, like
GetProperty("Name", MemberKind.Public) or GetField("Name", MemberKind.Internal).
To get more metadata from a PropertyInfo, you can use extensions methods like:
IsExplictlyImplementedIsIndexerHasAttributeandHasAttributeInHierarchy, with an optional predicate to filter on attribute properties.GetAttributeandGetMatchingAttributesto retrieve the (single) attribute(s) a member is decorated with, with an optional predicate to filter on attribute properties. These do not consider the member's inheritance hierarchy; useHasAttributeInHierarchyif you need to know whether the attribute is present anywhere in it.IsPublic,IsInternal,IsProtected,IsPrivateorIsAbstractto check either the getter or setters matches the criteriaIsInitOnlyto detect C# 9 init-only properties,IsRequiredto detect the C# 11requiredmodifier, andIsWritableto see if a property can be assigned outside of an object initializer or constructorGetNullabilityandIsNullableReferenceto determine the nullable reference type annotation of the property
Similarly, you can find indexers using FindIndexers, conversion operators through FindImplicitConversionOperators
and FindExplicitConversionOperators, and methods via FindMethod, FindParameterlessMethod and HasMethod.
You can also enumerate all the methods of a type hierarchy with GetMethods, using the same MemberKind options as
GetProperties. It skips property/event accessors, indexers and operators by default, and de-duplicates overridden
or new-hidden methods so only the most derived one is returned.
Events follow the same visibility and hierarchy rules as properties, so use GetEvents and FindEvent the same way
you would use GetProperties and FindProperty. To get metadata from an EventInfo, use IsExplicitlyImplemented,
IsPublic, IsInternal, IsProtected, IsPrivate or IsAbstract, which check either the add or remove accessor.
Constructors are not inherited, so GetConstructors and FindConstructor only look at the constructors declared
directly on the type you ask for, using the same MemberKind visibility flags. Omitting the parameter types on
FindConstructor means the parameterless constructor, just like Type.GetConstructor(Type.EmptyTypes) does.
HasDefaultConstructor tells you whether the type has a public parameterless constructor (or is a value type, which
always has one), the kind of constructor Activator.CreateInstance(Type) requires.
For a FieldInfo, you can use GetNullability and IsNullableReference in the same way as for PropertyInfo.
For ParameterInfo, you can use:
HasAttributeandHasAttributeInHierarchyto check whether a parameter is decorated with a specific attribute, with an optional predicate to filter on attribute properties.GetAttributeandGetMatchingAttributesto retrieve the (single) attribute(s) a parameter is decorated with, with an optional predicate to filter on attribute properties.GetNullabilityandIsNullableReferenceto determine the nullable reference type annotation of the parameter.
Other extension methods act on Type directly and include:
IsDerivedFromOpenGenericandGetClosedGenericInterfaces- Various
HasAttribute,HasAttributeInHierarchy,GetAttributeandGetMatchingAttributesoverloads, with and without additional filtering. IsObsoleteto detect obsolete types and members, including members declared on obsolete types.OverridesEqualsto determine if a type implements value semanticsIsSameOrInheritsto see if a type is the same as or derives from another (open-generic) typeIsCompilerGeneratedandHasFriendlyNameto see if a type is (partially) generated by the compiler, like records, tuples, etc.IsAnonymous,IsTuple,IsRecord,IsRecordClass,IsRecordStruct,IsKeyValuePair,IsDelegate,IsStruct,IsRefStructto find these types.IsReadOnlyStructto detect readonly structs, andIsFileLocalto detect C# 11file-local types.GetNonGenericNameto get the name of a type without the generic backtick and number of parameters.GetFriendlyNameandGetFullFriendlyNameto render a type the way a C# developer would write it, e.g.Dictionary<string, List<int>>orint?, optionally including the full namespace.IsNullableto check whether a type is a constructedNullable<T>.IsEnumerableandGetElementTypeOfEnumerableto check whether a type is an enumerable (excludingstring) and, if so, get its element type.IsDictionaryandTryGetDictionaryTypesto check whether a type is a dictionary and, if so, get its key and value types.IsAwaitableto check whether a type can be awaited usingawait, based on the compiler's awaitable pattern.IsTaskLiketo check whether a type isTask,Task<T>,ValueTask, orValueTask<T>.IsNumericto check whether a type is one of the numeric primitive types (includingdecimal).IsPrimitiveOrStringto check whether a type is a CLR primitive orstring.
Additionally, Reflectify offers some helpers such as
NullableOrActualTypeto get the actual type of a nullable type or the type itself if it's not nullable.
GetNullability returns a Nullability enum (Unknown, NotNull or Nullable) that reflects the compiler-emitted
nullable reference type metadata for reference types, and treats value types consistently with NullableOrActualType
(e.g. int is NotNull, int? is Nullable). IsNullableReference is a convenience shortcut for
GetNullability() == Nullability.Nullable. On .NET 6 and later this is backed by NullabilityInfoContext; on older
targets it's determined by reading the compiler's NullableAttribute/NullableContextAttribute metadata directly.
This library is available as a NuGet package on https://nuget.org. To install it, use the following command-line:
dotnet add package Reflectify
Your contributions are always welcome! Please have a look at the contribution guidelines first.
(Made with contrib.rocks)
This library uses Semantic Versioning to give meaning to the version numbers. For the versions available, see the tags on this repository.
This library wouldn't have been possible without the following tools, packages and companies:
- Nuke - Smart automation for DevOps teams and CI/CD pipelines
- Rider - The world's most loved .NET and game dev IDE
- xUnit - Community-focused unit testing tool for .NET.
- Coverlet - Cross platform code coverage for .NET
- Polysharp - Generated, source-only polyfills for C# language features
- GitVersion - From git log to SemVer in no time
- ReportGenerator - Powerful code coverage visualization
- My Blog
- Mockly - Fluent HTTP mocking for .NET like it should have been done
- Pathy - Fluently building and using file and directory paths without binary dependencies
- FluentAssertions - Extension methods to fluently assert the outcome of .NET tests
- C# Coding Guidelines - Forkable coding guidelines for all C# versions
This project is licensed under the MIT License - see the LICENSE.md file for details.