ToolBX.Reflection4Humans.Extensions 2.2.0

There is a newer prerelease version of this package available.
See the version list below for details.
dotnet add package ToolBX.Reflection4Humans.Extensions --version 2.2.0
NuGet\Install-Package ToolBX.Reflection4Humans.Extensions -Version 2.2.0
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="ToolBX.Reflection4Humans.Extensions" Version="2.2.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add ToolBX.Reflection4Humans.Extensions --version 2.2.0
#r "nuget: ToolBX.Reflection4Humans.Extensions, 2.2.0"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install ToolBX.Reflection4Humans.Extensions as a Cake Addin
#addin nuget:?package=ToolBX.Reflection4Humans.Extensions&version=2.2.0

// Install ToolBX.Reflection4Humans.Extensions as a Cake Tool
#tool nuget:?package=ToolBX.Reflection4Humans.Extensions&version=2.2.0

Reflection4Humans

Reflection4Humans.Extensions

Reflection extension methods meant to be used by humans.

Member search extensions

GetAll[MEMBER]

  • Type.GetAllMembers
  • Type.GetAllProperties
  • Type.GetAllFields
  • Type.GetAllMethods
  • Type.GetAllConstructors
  • Type GetAllEvents

The above extension methods will return all members of said kind on any .NET type. There is no confusing flag for which you need to specify whether or not you want private, protected or static members. It's all done via predicates.

//Returns all members including those on inherited types
var allMembers = typeof(Dummy).GetAllMembers();

//Returns all private members that start with "Johnny"
var members = typeof(Dummy).GetAllMembers(x => x.Name.StartsWith("Johnny") && x.IsPrivate());

//Returns all get-only static properties
var properties = typeof(Dummy).GetAllProperties(x => x.IsGet() && !x.IsSet() && x.IsStatic());

//Returns public fields only
var fields = typeof(Dummy).GetAllFields(x => x.IsPublic());

//Returns methods that have parameters of string, char and int (in that order)
var methods = typeof(Dummy).GetAllMethods(x => x.HasParameters<string, char, int>());

//You can use some of the same approach for constructors as you would regular methods
var constructors = typeof(Dummy).GetAllConstructors(x => x.HasParameters<int>() && !x.IsStatic());

GetSingle[MEMBER] & GetSingle[MEMBER]OrDefault

  • Type.GetSingleMember & Type.GetSingleMemberOrDefault
  • Type.GetSingleProperty & Type.GetSinglePropertyOrDefault
  • Type.GetSingleField & Type.GetSingleFieldOrDefault
  • Type.GetSingleMethod & Type.GetSingleMethodOrDefault
  • Type.GetSingleConstructor & Type.GetSingleConstructorOrDefault
  • Type.GetSingleEvent & Type.GetSingleEventOrDefault

As you probably expect, the overload without "Default" in it will throw an exception if there is no member found. That is the only difference between the two. They are used the exact same way as the above "GetAll" extensions. There are additional overloads that do a simple search by name but they will throw an exception if there is more than one result to your query so make sure that there is indeed only one member by that name.

//Will return a single get-only property from the Dummy type or will throw if there is more than one public get-only property
var property = typeof(Dummy).GetSingleProperty(x => x.IsPublic() && !x.IsSet())

//It may be better to go by name in the case of properties if you can
var propertyByName = typeof(Dummy).GetSingleProperty("Level");

//But in the case of methods, multiple ones can share the same name and even some parameters. It can be difficult to find the right one in some cases
var method = typeof(Dummy).GetSingleMethodOrDefault(x => x.Name == "LevelUp" && x.HasParameters<int, string>() && x.IsGeneric());

Type.GetHumanReadableName

Have you ever wanted to output a type name in an exception message before only for it to read like this?

"Reflection4Humans.Extensions.Tests.Dummy`1[System.String] did something weird!"

Wouldn't it have been easier on the eyes if it had said this instead?

"Dummy<String> did something weird!"

This is what this method helps you achieve.

//Instead of this
typeof(Dummy<string>).Name

//Use this
typeof(Dummy<string>).GetHumanReadableName();

Type.IsAttribute

//Isn't it weird that you have the following in cs
var isInterface = type.IsInterface;
var isAbstract = type.IsAbstract;
var isClass = type.IsClass;
var isGenericType = type.IsGenericType;

//But not this?
var isAttribute = type.IsAttribute();

Well now you have it.

Type.GetPropertyPath

//Say you have a multi-level object like this
public record Person
{
	public string Name { get; init; }
	public Job Job { get; init; }
}

//Maybe you would like to have code looking at the Salary from a Person object
public record Job
{
	public string Title { get; init; }
	public decimal Salary { get; init; }
}

public void DoStuff()
{
	//The propertyPath variable now holds the PropertyInfo objects for Person's Job property as well as Job's Salary property, 
	//including the types for Person and Job. Essentially looking something like this : 
	//{ { Property = [Job PropertyInfo], Owner = [Person type object] }, { Property = [Salary PropertyInfo], Owner = [Job type object] } }
	var propertyPath = typeof(Person).GetPropertyPath("Job.Salary");

	...
}

Type.IsAttribute

True if the the type is an attribute.

if (type.IsAttribute())
{
	...
}

Type.GetDirectInterfaces

Returns all interfaces that the type implements. In other words, it excludes those that are implemented "indirectly" via a base class.

var directInterfaces = type.GetDirectInterfaces();

Type.Implements

Provides an easy way to check whether or not a type implements an interface (directly OR indirectly).

if (type.Implements<IDisposable>)
{
	...
}

//Also comes with a non-generic overload
if (type.Implements(typeof(IDisposable))
{
	...
}

Type.DirectlyImplements

Returns true when a type directly implements an interface (as opposed to the "regular" Implements method). It is also used the same as the Implements method.

if (type.DirectlyImplements<IDisposable>)
{
	...
}

//Also comes with a non-generic overload
if (type.DirectlyImplements(typeof(IDisposable))
{
	...
}

Type.HasInterface

True if the type implements at least one interface.

if (type.HasInterface())
{
	...
}

Type.HasAttribute

  • HasAttribute()
//True if the type has at least one attribute of any type
if (type.HasAttribute())
{
	...
}
  • HasAttribute<TAttribute>()
//Is true if the type has an attribute of type AutoInjectAttribute regardless of the attribute's properties
if (type.HasAttribute<AutoInjectAttribute>())
{
	...
}

//Can also be used to check the attribute's properties as well
if (type.HasAttribute<AutoInjectAttribute>(x => x.Interface == typeof(IDummy)))
{
	...
}

//There is also a non-generic overload but it can't be used to check the attributes' properties
if (type.HasAttribute(typeof(AutoInjectAttribute))
{
	...
}

MemberInfo extensions

  • IsStatic
  • IsInstance
  • IsPrivate
  • IsProptected
  • IsInternal
  • IsPublic
  • IsConstructor
  • IsMethod
  • IsField
  • IsProperty

These are meant to make it easier to search MemberInfo but could be used in other scenarios as well.

MethodInfo & MethodBase extensions

  • HasParameters
//Returns true if the method has a signature of string, char and long (in this precise order)
if (method.HasParameters<string, char, long>()) 
{
	...
}

//It also comes with a non-generic overload
if (method.HasParameters(typeof(string), typeof(char), typeof(long))
{
	...
}
  • HasParameters(count)
//True if the constructor has exactly two parameters
if (constructor.HasParameters(2))
{
	...
}
  • HasNoParameter
//True if the method has no parameter
if (method.HasNoParameter())
{
	...
}

PropertyInfo

  • IsStatic
//Normally, you would need to access the get or set method to check whether or not the property is static. Now you can check out the property directly.
if (property.IsStatic())
{
	...
}
  • IsGet
//True if the property has a get accessor
if (property.IsGet())
{
	...
}
  • IsSet
//True if the property has a set accessor
if (property.IsSet())
{
	...
}
Product Compatible and additional computed target framework versions.
.NET net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net7.0

    • No dependencies.

NuGet packages (10)

Showing the top 5 NuGet packages that depend on ToolBX.Reflection4Humans.Extensions:

Package Downloads
ToolBX.Reflection4Humans.TypeFetcher

Provides a more straightforward way for a human being to get types from all loaded assemblies using the TypeFetcher class.

ToolBX.Reflection4Humans.ValueEquality

Adds extensions to automatically compare objects by value.

ToolBX.Collections.ObservableList

A modern re-implementation of a dynamic one-dimensional array.

ToolBX.Collections.ReadOnly

Actual read-only collections with helper extension methods to make them less painful to use.

ToolBX.Collections.Grid

An observable, dynamic two-dimensional array.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
3.0.0-beta1 74 5/31/2024
2.2.0 8,452 1/11/2024
2.2.0-beta9 393 1/7/2024
2.2.0-beta8 163 12/29/2023
2.2.0-beta7 206 12/14/2023
2.2.0-beta6 159 12/14/2023
2.2.0-beta4 230 11/16/2023
2.2.0-beta3 89 11/15/2023
2.2.0-beta2 126 8/16/2023
2.2.0-beta1 348 7/24/2023
2.1.0-beta1 119 6/28/2023
2.0.3 12,800 6/19/2023
2.0.2 2,038 4/23/2023
2.0.1 207 2/17/2023
2.0.1-beta2 115 2/16/2023
2.0.1-beta1 123 2/14/2023
2.0.0 1,242 11/9/2022
2.0.0-beta1 366 9/20/2022
1.0.0 10,780 12/24/2021