Note
If you want to access a property by name rather than by a PropertyInfo, then you can use the SetProperty
and GetProperty methods in the Reflector class, which have some overloads with a propertyName parameter.
public abstract class PropertyAccessor : MemberAccessor
Public MustInherit Class PropertyAccessor
Inherits MemberAccessor
public ref class PropertyAccessor abstract : public MemberAccessor
[<AbstractClassAttribute>]
type PropertyAccessor =
class
inherit MemberAccessor
end
You can obtain a PropertyAccessor instance by the static GetAccessor method.
The Get(Object, Object) and Set(Object, Object, Object) methods can be used to get or set the property in general cases. These methods can be used for any properties, including indexed ones.
The other non-generic Get and Set overloads can be used for simple properties or for indexers with one index parameter.
If you know the property type at compile time, then you can use the generic GetStaticValue/SetStaticValue methods for static properties. If you know also the instance type (and the index parameter for indexers), then the GetInstanceValue/SetInstanceValue methods can be used to access instance properties with better performance. These generic methods can be used for properties with no more than one index parameter.
The first call of these methods are slower because the delegates are generated on the first access, but further calls are much faster.
The already obtained accessors are cached so subsequent GetAccessor calls return the already created accessors unless they were dropped out from the cache, which can store about 8000 elements.
using System;
using System.Reflection;
using System.Runtime.Versioning;
using KGySoft.Diagnostics;
using KGySoft.Reflection;
class Example
{
private class TestClass
{
public int TestProperty { get; set; }
}
private static string PlatformName => ((TargetFrameworkAttribute)Attribute.GetCustomAttribute(Assembly.GetExecutingAssembly(),
typeof(TargetFrameworkAttribute))).FrameworkDisplayName;
static void Main(string[] args)
{
var instance = new TestClass();
PropertyInfo property = instance.GetType().GetProperty(nameof(TestClass.TestProperty));
PropertyAccessor accessor = PropertyAccessor.GetAccessor(property);
new PerformanceTest { TestName = $"Set Property - {PlatformName}", Iterations = 1_000_000 }
.AddCase(() => instance.TestProperty = 1, "Direct set")
.AddCase(() => property.SetValue(instance, 1), "System.Reflection.PropertyInfo.SetValue")
.AddCase(() => accessor.Set(instance, 1), "PropertyAccessor.Set")
.AddCase(() => accessor.SetInstanceValue(instance, 1), "PropertyAccessor.SetInstanceValue<,>")
.DoTest()
.DumpResults(Console.Out);
new PerformanceTest<int> { TestName = $"Get Property - {PlatformName}", Iterations = 1_000_000 }
.AddCase(() => instance.TestProperty, "Direct get")
.AddCase(() => (int)property.GetValue(instance), "System.Reflection.PropertyInfo.GetValue")
.AddCase(() => (int)accessor.Get(instance), "PropertyAccessor.Get")
.AddCase(() => accessor.GetInstanceValue<TestClass, int>(instance), "PropertyAccessor.GetInstanceValue<,>")
.DoTest()
.DumpResults(Console.Out);
}
}
// This code example produces a similar output to these ones:
// ==[Set Property - .NET 8.0 Results]================================================
// Iterations: 1,000,000
// Warming up: Yes
// Test cases: 4
// Calling GC.Collect: Yes
// Forced CPU Affinity: No
// Cases are sorted by time (quickest first)
// --------------------------------------------------
// 1. Direct set: average time: 3.02 ms
// 2. PropertyAccessor.SetInstanceValue<,>: average time: 4.70 ms (+1.67 ms / 155.43%)
// 3. PropertyAccessor.Set: average time: 11.60 ms (+8.58 ms / 384.08%)
// 4. System.Reflection.PropertyInfo.SetValue: average time: 25.79 ms (+22.77 ms / 853.68%)
//
// ==[Get Property - .NET 8.0 Results]================================================
// Iterations: 1,000,000
// Warming up: Yes
// Test cases: 4
// Calling GC.Collect: Yes
// Forced CPU Affinity: No
// Cases are sorted by time (quickest first)
// --------------------------------------------------
// 1. Direct get: average time: 2.86 ms
// 2. PropertyAccessor.GetInstanceValue<,>: average time: 4.80 ms (+1.95 ms / 168.15%)
// 3. PropertyAccessor.Get: average time: 11.56 ms (+8.71 ms / 404.98%)
// 4. System.Reflection.PropertyInfo.GetValue: average time: 17.05 ms (+14.20 ms / 597.12%)
// ==[Set Property - .NET Framework 4.8 Results]================================================
// Iterations: 1,000,000
// Warming up: Yes
// Test cases: 4
// Calling GC.Collect: Yes
// Forced CPU Affinity: No
// Cases are sorted by time (quickest first)
// --------------------------------------------------
// 1. Direct set: average time: 3.63 ms
// 2. PropertyAccessor.SetInstanceValue<,>: average time: 12.05 ms (+8.42 ms / 331.91%)
// 3. PropertyAccessor.Set: average time: 18.20 ms (+14.57 ms / 501.41%)
// 4. System.Reflection.PropertyInfo.SetValue: average time: 186.50 ms (+182.87 ms / 5,137.78%)
//
// ==[Get Property - .NET Framework 4.8 Results]================================================
// Iterations: 1,000,000
// Warming up: Yes
// Test cases: 4
// Calling GC.Collect: Yes
// Forced CPU Affinity: No
// Cases are sorted by time (quickest first)
// --------------------------------------------------
// 1. Direct get: average time: 3.51 ms
// 2. PropertyAccessor.GetInstanceValue<,>: average time: 11.12 ms (+7.62 ms / 317.21%)
// 3. PropertyAccessor.Get: average time: 15.01 ms (+11.50 ms / 428.04%)
// 4. System.Reflection.PropertyInfo.GetValue: average time: 120.99 ms (+117.49 ms / 3,450.32%)
CanRead | Gets whether the property can be read (has get accessor). |
CanWrite | Gets whether the property can be written (has set accessor or is a ref property). |
MemberInfo |
Gets the reflection member info of the accessed member.
(Inherited from MemberAccessor) |
Equals |
Determines whether the specified Object is equal to the current MemberAccessor.
(Inherited from MemberAccessor) |
Get(Object) |
Gets the value of the property with no index parameters.
For static properties the instance parameter is omitted (can be ).
See the Remarks section of the Get(Object, Object) overload for details. |
Get(Object, Object) |
Gets the value of the property with one index parameter.
For static properties the instance parameter is omitted (can be ).
See the Remarks section of the Get(Object, Object) overload for details. |
Get(Object, Object) | Gets the value of the property. For static properties the instance parameter is omitted (can be ). If the property is not an indexer, then indexParameters parameter is omitted. |
GetAccessor | Gets a PropertyAccessor for the specified property. |
GetHashCode |
Gets a hash code for the current MemberAccessor instance.
(Inherited from MemberAccessor) |
GetInstanceValueTInstance, TProperty(TInstance) | Gets the strongly typed value of a non-indexed instance property in a reference type. If the type of the property or the declaring instance is not known at compile time the non-generic Set methods can be used. |
GetInstanceValueTInstance, TProperty(TInstance) | Gets the strongly typed value of a non-indexed instance property in a value type. If the type of the property or the declaring instance is not known at compile time the non-generic Set methods can be used. |
GetInstanceValueTInstance, TProperty, TIndex(TInstance, TIndex) | Gets the strongly typed value of a single-parameter indexed property in a reference type. If the type of the property, the declaring instance or the index parameter is not known at compile time, or the indexer has more than one parameter, then the non-generic Set methods can be used. |
GetInstanceValueTInstance, TProperty, TIndex(TInstance, TIndex) | Gets the strongly typed value of a single-parameter indexed property in a value type. If the type of the property, the declaring instance or the index parameter is not known at compile time, or the indexer has more than one parameter, then the non-generic Set methods can be used. |
GetStaticValueTProperty | Gets the strongly typed value of a static property. If the type of the property is not known at compile time the non-generic Set methods can be used. |
Set(Object, Object) |
Sets the property with no index parameters.
For static properties the instance parameter is omitted (can be ).
See the Remarks section of the Set(Object, Object, Object) overload for details. |
Set(Object, Object, Object) |
Sets the property with one index parameter.
For static properties the instance parameter is omitted (can be ).
See the Remarks section of the Set(Object, Object, Object) overload for details. |
Set(Object, Object, Object) | Sets the property. For static properties the instance parameter is omitted (can be ). If the property is not an indexer, then indexParameters parameter is omitted. |
SetInstanceValueTInstance, TProperty(TInstance, TProperty) | Sets the strongly typed value of a non-indexed instance property in a value type. If the type of the property or the declaring instance is not known at compile time the non-generic Set methods can be used. |
SetInstanceValueTInstance, TProperty(TInstance, TProperty) | Sets the strongly typed value of a non-indexed instance property in a reference type. If the type of the property or the declaring instance is not known at compile time the non-generic Set methods can be used. |
SetInstanceValueTInstance, TProperty, TIndex(TInstance, TProperty, TIndex) | Sets the strongly typed value of a single-parameter indexed property in a value type. If the type of the property, the declaring instance or the index parameter is not known at compile time, or the indexer has more than one parameter, then the non-generic Set methods can be used. |
SetInstanceValueTInstance, TProperty, TIndex(TInstance, TProperty, TIndex) | Sets the strongly typed value of a single-parameter indexed property in a reference type. If the type of the property, the declaring instance or the index parameter is not known at compile time, or the indexer has more than one parameter, then the non-generic Set methods can be used. |
SetStaticValueTProperty | Sets the strongly typed value of a static property. If the type of the property is not known at compile time the non-generic Set methods can be used. |
ToString |
Returns a String that represents the current MemberAccessor.
(Inherited from MemberAccessor) |
Convert |
Converts an Object specified in the obj parameter to the desired targetType.
See the Examples section of the generic ConvertTTarget(Object, CultureInfo) overload for an example. (Defined by ObjectExtensions) |
ConvertTTarget |
Converts an Object specified in the obj parameter to the desired TTarget.
(Defined by ObjectExtensions) |
In |
Gets whether item is among the elements of set.
See the Examples section of the generic InT(T, T) overload for an example. (Defined by ObjectExtensions) |
TryConvert |
Tries to convert an Object specified in the obj parameter to the desired targetType.
See the Examples section of the ConvertTTarget(Object, CultureInfo) method for a related example. (Defined by ObjectExtensions) |
TryConvert |
Tries to convert an Object specified in the obj parameter to the desired targetType.
See the Examples section of the ConvertTTarget(Object, CultureInfo) method for a related example. (Defined by ObjectExtensions) |
TryConvertTTarget |
Tries to convert an Object specified in the obj parameter to the desired TTarget.
See the Examples section of the ConvertTTarget(Object, CultureInfo) method for a related example. (Defined by ObjectExtensions) |
TryConvertTTarget |
Tries to convert an Object specified in the obj parameter to the desired TTarget.
See the Examples section of the ConvertTTarget(Object, CultureInfo) method for a related example. (Defined by ObjectExtensions) |