Use typed delegates for faster invoke

This commit is contained in:
XtraCube authored and miniduikboot committed 2026-06-10 00:24:01 +02:00
1 parent 6381d79a18
commit c3775ff33f
1 file changed
+49 -12
@@ -25,6 +25,16 @@ public class CompilerGeneratedObjectWrapper
/// </summary> /// </summary>
protected Dictionary<string, PropertyInfo> PropertyCache { get; } protected Dictionary<string, PropertyInfo> PropertyCache { get; }
/// <summary>
/// Gets the getter cache for faster property access.
/// </summary>
protected Dictionary<string, Delegate> GetterCache { get; }
/// <summary>
/// Gets the setter cache for faster property access.
/// </summary>
protected Dictionary<string, Delegate> SetterCache { get; }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="CompilerGeneratedObjectWrapper"/> class. /// Initializes a new instance of the <see cref="CompilerGeneratedObjectWrapper"/> class.
/// </summary> /// </summary>
@@ -35,6 +45,31 @@ public class CompilerGeneratedObjectWrapper
GeneratedType = generatedObject.GetType(); GeneratedType = generatedObject.GetType();
PropertyCache = []; PropertyCache = [];
GetterCache = [];
SetterCache = [];
}
public PropertyInfo CacheProperty<T>(string fieldName)
{
var propertyInfo = AccessTools.Property(GeneratedType, fieldName)
?? throw new MissingMemberException(
$"Could not find field '{fieldName}' in type '{GeneratedType}'.");
if (propertyInfo.PropertyType != typeof(T))
{
throw new InvalidCastException(
$"Field '{fieldName}' is of type '{propertyInfo.PropertyType}', not '{typeof(T)}'.");
}
PropertyCache[fieldName] = propertyInfo;
var funcType = typeof(Func<T>);
GetterCache[fieldName] = propertyInfo.GetMethod!.CreateDelegate(funcType, GeneratedObject);
var actionType = typeof(Action<T>);
SetterCache[fieldName] = propertyInfo.SetMethod!.CreateDelegate(actionType, GeneratedObject);
return propertyInfo;
} }
/// <summary> /// <summary>
@@ -48,12 +83,12 @@ public class CompilerGeneratedObjectWrapper
{ {
if (!PropertyCache.TryGetValue(fieldName, out var propertyInfo)) if (!PropertyCache.TryGetValue(fieldName, out var propertyInfo))
{ {
propertyInfo = AccessTools.Property(GeneratedType, fieldName); propertyInfo = CacheProperty<TField>(fieldName);
if (propertyInfo == null) }
{
throw new MissingMemberException($"Could not find field '{fieldName}' in type '{GeneratedType}'."); if (GetterCache.TryGetValue(fieldName, out var getter))
} {
PropertyCache[fieldName] = propertyInfo; return ((Func<TField>) getter)();
} }
return (TField) propertyInfo.GetValue(GeneratedObject)!; return (TField) propertyInfo.GetValue(GeneratedObject)!;
@@ -70,14 +105,16 @@ public class CompilerGeneratedObjectWrapper
{ {
if (!PropertyCache.TryGetValue(fieldName, out var propertyInfo)) if (!PropertyCache.TryGetValue(fieldName, out var propertyInfo))
{ {
propertyInfo = AccessTools.Property(GeneratedType, fieldName); propertyInfo = CacheProperty<TField>(fieldName);
if (propertyInfo == null) }
{
throw new MissingMemberException($"Could not find field '{fieldName}' in type '{GeneratedType}'."); if (SetterCache.TryGetValue(fieldName, out var setter))
} {
PropertyCache[fieldName] = propertyInfo; ((Action<TField>) setter)(value);
return;
} }
propertyInfo.SetValue(GeneratedObject, value); propertyInfo.SetValue(GeneratedObject, value);
} }
} }