Reflectless 1.0.5
dotnet add package Reflectless --version 1.0.5
NuGet\Install-Package Reflectless -Version 1.0.5
<PackageReference Include="Reflectless" Version="1.0.5" />
<PackageVersion Include="Reflectless" Version="1.0.5" />
<PackageReference Include="Reflectless" />
paket add Reflectless --version 1.0.5
#r "nuget: Reflectless, 1.0.5"
#:package Reflectless@1.0.5
#addin nuget:?package=Reflectless&version=1.0.5
#tool nuget:?package=Reflectless&version=1.0.5
Reflectless
Reflectless is a library designed to access properties, fields, constructors and methods by name without using reflection. Reflectless is useful when members of given class discovered using reflection and then required to read or write. This is very useful if the number of operations are very high and possible uses include serialisation or ORM frameworks.
Installation
Install the package via NuGet:
Install-Package Reflectless
Or use the .NET CLI:
dotnet add package Reflectless
Getting Started
Here’s a quick example to demonstrate how to use Reflectless:
var instance = new Example { Name = "John", Age = 30 };
var properties = typeof(Example).GetProperties();
foreach (var propertyInfo in properties)
{
var getter = Reflectless.Reflectless.GetPropertyGetAccessor(typeof(Example), propertyInfo.Name);
var value = getter(instance);
Console.WriteLine($"Property {propertyInfo.Name}: {value}");
}
public class Example
{
public string Name { get; set; }
public int Age { get; set; }
}
//Output:
//Property Name: John
//Property Age: 30
Cache
Accessing via Reflectless.<method name> caches the result so that the subsequent access is faster. For some reason the cache is not required or a custom cache is required ReflectlessNoCache.<method name> can be used.
Note: Not recommanded to use without provided cache or a custom cache since it will have a significant performance impact.
Non-Generic and Generic approaches
There are 2 different ways of doing the same operation.
Non generic (method with parameters) approach:
This approach is the probably most useful as it can be used with reflection discovered members of a class to manipulate values.
Generic appraoch
With this approach the generic signatures required.
Examples
Read Fields
var instance = new Example { _name = "John" };
//non generic approach
var nonGenericAccessor = Reflectless.Reflectless.GetFieldGetAccessor(typeof(Example), "_name");
Console.WriteLine($"Non generic : {nonGenericAccessor(instance)}");
//generic approach
var genericAccessor = Reflectless.Reflectless.GetFieldGetAccessor<Example,string>("_name");
Console.WriteLine($"Generic : {genericAccessor(instance)}");
public class Example
{
public string _name;
}
//Output:
//Non generic : John
//Generic : John
Write Fields
var instance = new Example { _name = "John" };
//non generic approach
var nonGenericAccessor = Reflectless.Reflectless.GetFieldSetAccessor(typeof(Example), "_name");
nonGenericAccessor(instance, "Peter");
Console.WriteLine($"Non generic : {instance._name}");
//generic approach
var genericAccessor = Reflectless.Reflectless.GetFieldSetAccessor<Example,string>("_name");
genericAccessor(instance, "Steve");
Console.WriteLine($"Generic : {instance._name}");
public class Example
{
public string _name;
}
//Output:
//Non generic : Peter
//Generic : Steve
Read Properties
var instance = new Example { Name = "John" };
//non generic approach
var nonGenericAccessor = Reflectless.Reflectless.GetPropertyGetAccessor(typeof(Example), "Name");
Console.WriteLine($"Non generic : {nonGenericAccessor(instance)}");
//generic approach
var genericAccessor = Reflectless.Reflectless.GetPropertyGetAccessor<Example, string>("Name");
Console.WriteLine($"Generic : {genericAccessor(instance)}");
public class Example
{
public string Name { get; set; }
}
//Output:
//Non generic : John
//Generic : John
Write Properties
var instance = new Example { Name = "John" };
//non generic approach
var nonGenericAccessor = Reflectless.Reflectless.GetPropertySetAccessor(typeof(Example), "Name");
nonGenericAccessor(instance, "Peter");
Console.WriteLine($"Non generic : {instance.Name}");
//generic approach
var genericAccessor = Reflectless.Reflectless.GetPropertySetAccessor<Example,string>("Name");
genericAccessor(instance, "Steve");
Console.WriteLine($"Generic : {instance.Name}");
public class Example
{
public string Name { get; set; }
}
//Output:
//Non generic : Peter
//Generic : Steve
Create Instances
//default constructor with non generic approach
var defaultNonGenericConstructorAccessor = Reflectless.Reflectless.GetDefaultConstructorAccessor(typeof(Example));
var instance1 = (Example)defaultNonGenericConstructorAccessor();
Console.WriteLine($"instance 1 : {instance1.Name}");
//default constructor with generic approach
var defaultGenericConstructorAccessor = Reflectless.Reflectless.GetDefaultConstructorAccessor<Example>();
var instance2 = defaultGenericConstructorAccessor();
Console.WriteLine($"instance 2 : {instance2.Name}");
//parameterised constructor with non generic approach
var nonGenericParameterConstructorAccessor = Reflectless.Reflectless.GetConstructorAccessor<Func<object,object>>(typeof(Example),typeof(string));
var instance3 = (Example)nonGenericParameterConstructorAccessor("Adipa");
Console.WriteLine($"instance 3 : {instance3.Name}");
//parameterised constructor with generic approach
var genericParameterConstructorAccessor = Reflectless.Reflectless.GetConstructorAccessor<Func<string,Example>>();
var instance4 = genericParameterConstructorAccessor("Steve");
Console.WriteLine($"instance 4 : {instance4.Name}");
public class Example
{
public Example()
{
Name = "Peter";
}
public Example(string name)
{
Name = name;
}
public string Name { get; set; }
}
//Output:
//instance 1 : Peter
//instance 2 : Peter
//instance 3 : Adipa
//instance 4 : Steve
Calling Methods
var instance = new Example { Name = "John" };
//non generic approach
var nonGenericMethodAccessor = Reflectless.Reflectless.GetMethodAccessor<Func<object,object,object>>(typeof(Example), "AppendToName", typeof(string));
nonGenericMethodAccessor(instance, " Wick");
Console.WriteLine($"Non generic : {instance.Name}");
//generic approach
var genericMethodAccessor = Reflectless.Reflectless.GetMethodAccessor<Func<Example,string,string>>("AppendToName");
genericMethodAccessor(instance, "'s Dog");
Console.WriteLine($"Generic : {instance.Name}");
public class Example
{
public string AppendToName(string suffix)
{
Name += suffix;
return Name;
}
public string Name { get; set; }
}
//Output:
//Non generic : John Wick
//Generic : John Wick's Dog
Benchmark Results
There is a benchmark project in the solution, and the benchmark run produced the following results. The comparison shows that using Reflectless is significantly faster than Reflection.
BenchmarkDotNet v0.15.8, Windows 11 (10.0.26300.9711)
AMD Ryzen AI 9 HX 370 w/ Radeon 890M 2.00GHz, 1 CPU, 24 logical and 12 physical cores
.NET SDK 10.0.402
[Host] : .NET 10.0.13 (10.0.13, 10.0.1326.50504), X64 RyuJIT x86-64-v4
Job-GOIBJB : .NET 10.0.13 (10.0.13, 10.0.1326.50504), X64 RyuJIT x86-64-v4
| Type | Method | N | Mean | Error | StdDev | Gen0 | Allocated |
|---|---|---|---|---|---|---|---|
| BenchmarkPropertyGet | Reflection_GetProperty | 1000 | 7,091.206 ns | 69.2145 ns | 67.9779 ns | 2.6855 | 24000 B |
| BenchmarkPropertyGet | Reflectless_GetProperty | 1000 | 3,667.778 ns | 104.9710 ns | 98.1899 ns | 2.6855 | 24000 B |
| BenchmarkPropertyGet | Reflection_GetProperty | 10000 | 77,201.697 ns | 472.1725 ns | 463.7365 ns | 28.5645 | 240000 B |
| BenchmarkPropertyGet | Reflectless_GetProperty | 10000 | 37,203.117 ns | 1,765.5272 ns | 1,733.9838 ns | 28.5645 | 240000 B |
| BenchmarkPropertySet | Reflection_SetProperty | 1000 | 13,263.268 ns | 82.5499 ns | 77.2172 ns | 6.5918 | 56000 B |
| BenchmarkPropertySet | Reflectless_SetProperty | 1000 | 3,773.773 ns | 281.4522 ns | 276.4237 ns | 2.6855 | 24000 B |
| BenchmarkPropertySet | Reflection_SetProperty | 10000 | 134,744.482 ns | 1,668.4074 ns | 1,393.1957 ns | 66.8945 | 560000 B |
| BenchmarkPropertySet | Reflectless_SetProperty | 10000 | 34,914.250 ns | 1,634.2438 ns | 1,605.0460 ns | 28.5645 | 240000 B |
| BenchmarkFieldGet | Reflection_GetField | 1000 | 6,150.479 ns | 144.2216 ns | 141.6449 ns | 2.6855 | 24000 B |
| BenchmarkFieldGet | Reflectless_GetField | 1000 | 3,541.953 ns | 113.9935 ns | 111.9569 ns | 2.6855 | 24000 B |
| BenchmarkFieldGet | Reflection_GetField | 10000 | 63,996.318 ns | 2,388.6631 ns | 2,345.9865 ns | 28.5645 | 240000 B |
| BenchmarkFieldGet | Reflectless_GetField | 10000 | 35,141.649 ns | 1,694.4669 ns | 1,664.1931 ns | 28.5645 | 240000 B |
| BenchmarkFieldSet | Reflection_SetField | 1000 | 7,801.810 ns | 156.2033 ns | 153.4126 ns | 2.6855 | 24000 B |
| BenchmarkFieldSet | Reflectless_SetField | 1000 | 4,062.216 ns | 153.0248 ns | 150.2908 ns | 2.6855 | 24000 B |
| BenchmarkFieldSet | Reflection_SetField | 10000 | 73,925.997 ns | 1,037.6174 ns | 866.4575 ns | 28.5645 | 240000 B |
| BenchmarkFieldSet | Reflectless_SetField | 10000 | 37,822.661 ns | 1,688.9319 ns | 1,658.7569 ns | 28.5645 | 240000 B |
| BenchmarkConstructor | Reflection_Construct | 1000 | 9.445 ns | 0.5265 ns | 0.4925 ns | - | - |
| BenchmarkConstructor | Reflectless_Construct | 1000 | 9.443 ns | 0.4852 ns | 0.4539 ns | - | - |
| BenchmarkConstructor | Reflection_Construct | 10000 | 9.601 ns | 0.3954 ns | 0.3699 ns | - | - |
| BenchmarkConstructor | Reflectless_Construct | 10000 | 9.305 ns | 0.3537 ns | 0.3135 ns | - | - |
| BenchmarkMethod | Reflection_Method | 1000 | 15,324.945 ns | 130.7274 ns | 122.2825 ns | 9.5215 | 80000 B |
| BenchmarkMethod | Reflectless_Method | 1000 | 5,588.124 ns | 199.2177 ns | 195.6584 ns | 5.6152 | 48000 B |
| BenchmarkMethod | Reflection_Method | 10000 | 152,170.938 ns | 1,781.9858 ns | 1,666.8706 ns | 95.4590 | 800000 B |
| BenchmarkMethod | Reflectless_Method | 10000 | 57,538.040 ns | 2,441.7607 ns | 2,284.0245 ns | 57.3730 | 480000 B |
License
Reflectless is licensed under the MIT License.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. 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. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.1 is compatible. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.1
- No dependencies.
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Reflectless:
| Package | Downloads |
|---|---|
|
NDbGate
NDbGate is an object relational mapping framework. What it differs from other ORM frameworks is that it gives the complete control over how the persistence/retrieval takes place at entity level. This is achieved by means of overriding/implementing methods provided in the base entity classes. |
GitHub repositories
This package is not used by any popular GitHub repositories.