From 38b570e9983db15e0665ac75931061e40d159b52 Mon Sep 17 00:00:00 2001 From: Ionite Date: Sat, 2 Dec 2023 15:04:38 -0500 Subject: [PATCH] Add TObject overload for GetPrivateField --- .../Extensions/ObjectExtensions.cs | 42 +++++++++++++++++++ .../StabilityMatrix.Core.csproj | 1 + 2 files changed, 43 insertions(+) diff --git a/StabilityMatrix.Core/Extensions/ObjectExtensions.cs b/StabilityMatrix.Core/Extensions/ObjectExtensions.cs index 9cbd9923..16743710 100644 --- a/StabilityMatrix.Core/Extensions/ObjectExtensions.cs +++ b/StabilityMatrix.Core/Extensions/ObjectExtensions.cs @@ -1,8 +1,10 @@ using System.Reflection; +using JetBrains.Annotations; using RockLib.Reflection.Optimized; namespace StabilityMatrix.Core.Extensions; +[PublicAPI] public static class ObjectExtensions { /// @@ -24,6 +26,10 @@ public static class ObjectExtensions /// /// Get the value of a named private field from an object /// + /// + /// The field must be defined by the runtime type of or its first base type. + /// For higher inheritance levels, use to specify the exact defining type. + /// public static T? GetPrivateField(this object obj, string fieldName) { // Check cache @@ -55,6 +61,42 @@ public static class ObjectExtensions return (T?)fieldGetter(obj); } + /// + /// Get the value of a named private field from an object + /// + /// Type of the object that defines the field, must be a base class of + /// Type of the field + public static T? GetPrivateField(this TObject obj, string fieldName) + where TObject : class + { + // Check cache + var fieldGetterCache = FieldGetterTypeCache.GetOrAdd(typeof(TObject)); + + if (!fieldGetterCache.TryGetValue(fieldName, out var fieldGetter)) + { + // Get the field + var field = typeof(TObject).GetField( + fieldName, + BindingFlags.Instance | BindingFlags.NonPublic + ); + + if (field is null) + { + throw new ArgumentException( + $"Field {typeof(TObject).Name}.{fieldName} not found on type {obj.GetType().Name}" + ); + } + + // Create a getter for the field + fieldGetter = field.CreateGetter(); + + // Add to cache + fieldGetterCache.Add(fieldName, fieldGetter); + } + + return (T?)fieldGetter(obj); + } + /// /// Set the value of a named private field on an object /// diff --git a/StabilityMatrix.Core/StabilityMatrix.Core.csproj b/StabilityMatrix.Core/StabilityMatrix.Core.csproj index 65fa8f17..30bb6cda 100644 --- a/StabilityMatrix.Core/StabilityMatrix.Core.csproj +++ b/StabilityMatrix.Core/StabilityMatrix.Core.csproj @@ -25,6 +25,7 @@ +