DynamicPropertyAccess 1.0.2
dotnet add package DynamicPropertyAccess --version 1.0.2
NuGet\Install-Package DynamicPropertyAccess -Version 1.0.2
<PackageReference Include="DynamicPropertyAccess" Version="1.0.2" />
paket add DynamicPropertyAccess --version 1.0.2
#r "nuget: DynamicPropertyAccess, 1.0.2"
// Install DynamicPropertyAccess as a Cake Addin #addin nuget:?package=DynamicPropertyAccess&version=1.0.2 // Install DynamicPropertyAccess as a Cake Tool #tool nuget:?package=DynamicPropertyAccess&version=1.0.2
This library allows you to get or set values to properties by name. It uses compiled lambdas instead that are cached of reflection and is thread safe.
Getting Property Value
You can get property value by calling:
T ObjectExtensions.GetPropertyValue<T>(this object source, string propertyName)
Alternatively, you can create Func
that gets property value from an object by calling:
Func<object, object?> TypeExtensions.GetPropertyGetter(this Type type, string propertyName)
Setting Property Value
You can set property value by calling:
void ObjectExtensions.SetPropertyValue(this object source, string propertyName, object value)
Alternatively, you can create Func
that sets property value on an object by calling:
Action<object, object?> TypeExtensions.GetPropertySetter(this Type type, string propertyName)
Both methods have TryGet
pattern alternatives.
Benchmarks
You can see benchmark for GetPropertyValue
method for this library, DynamicPropertyAccessor, FastMember and Reflection.
Methods with ...Reused
suffix create Func
/PropertyInfo
once and then reuse it in benchmark.
BenchmarkDotNet=v0.13.5, OS=Windows 10 (10.0.19044.2604/21H2/November2021Update)
AMD Ryzen 7 3700X, 1 CPU, 16 logical and 8 physical cores
[Host] : .NET Framework 4.8 (4.8.4614.0), X64 RyuJIT VectorSize=256
.NET 7.0 : .NET 7.0.3 (7.0.323.6910), X64 RyuJIT AVX2
.NET Framework 4.7.2 : .NET Framework 4.8 (4.8.4614.0), X64 RyuJIT VectorSize=256
Method | Job | Runtime | Mean | Error | StdDev |
---|---|---|---|---|---|
DynamicPropertyAccess | .NET 7.0 | .NET 7.0 | 26.776 ns | 0.4549 ns | 0.4255 ns |
DynamicPropertyAccessor | .NET 7.0 | .NET 7.0 | 31.530 ns | 0.3986 ns | 0.3728 ns |
FastMember | .NET 7.0 | .NET 7.0 | 30.972 ns | 0.4472 ns | 0.4183 ns |
Reflection | .NET 7.0 | .NET 7.0 | 33.527 ns | 0.4686 ns | 0.4383 ns |
DynamicPropertyAccessReused | .NET 7.0 | .NET 7.0 | 1.475 ns | 0.0332 ns | 0.0311 ns |
FastMemberReused | .NET 7.0 | .NET 7.0 | 14.770 ns | 0.1585 ns | 0.1483 ns |
ReflectionReused | .NET 7.0 | .NET 7.0 | 12.105 ns | 0.2688 ns | 0.2514 ns |
DynamicPropertyAccess | .NET Framework 4.7.2 | .NET Framework 4.7.2 | 66.566 ns | 1.2969 ns | 1.3877 ns |
DynamicPropertyAccessor | .NET Framework 4.7.2 | .NET Framework 4.7.2 | 57.735 ns | 1.1492 ns | 1.4113 ns |
FastMember | .NET Framework 4.7.2 | .NET Framework 4.7.2 | 43.592 ns | 0.1853 ns | 0.1547 ns |
Reflection | .NET Framework 4.7.2 | .NET Framework 4.7.2 | 169.533 ns | 2.0884 ns | 1.6305 ns |
DynamicPropertyAccessReused | .NET Framework 4.7.2 | .NET Framework 4.7.2 | 5.731 ns | 0.0291 ns | 0.0227 ns |
FastMemberReused | .NET Framework 4.7.2 | .NET Framework 4.7.2 | 24.150 ns | 0.1821 ns | 0.1703 ns |
ReflectionReused | .NET Framework 4.7.2 | .NET Framework 4.7.2 | 120.565 ns | 2.4210 ns | 4.9455 ns |
As you can see, GetPropertyValue
is slightly slower on .NET Framework than available alternatives.
This is because of thread safety overhead. On the other hand, reused Func
from GetPropertyGetter
is significantly faster.
Additionally, Reflection is almost as fast on .NET 7+.
You can read more about it here.
Conclusions
- Use this library (and reuse Getter/Setter) if:
- Read/Write operations are frequently performed.
- Thread safety is important.
- Use other libraries if:
- Read/Write operations are rarely performed.
- Thread safety is not a concern.
- Target framework is .NET Framework, .NET 6 or below.
- Use Reflection if:
- Target framework is .NET 7+ and Read/Write operations are rarely performed.
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. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. 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.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.