// https://github.com/XtraCube/Reactor/blob/main/Reactor/Utilities/CompilerGeneratedObjectWrapper.cs
using System;
using System.Collections.Generic;
using System.Reflection;
using HarmonyLib;
namespace EHR.Modules;
///
/// A safe wrapper around compiler generated classes like DisplayClass or IEnumerator state machines.
///
public class CompilerGeneratedObjectWrapper
{
///
/// Gets a reference to the compiler generated object.
///
public object GeneratedObject { get; }
///
/// Gets the type of the compiler generated object.
///
protected Type GeneratedType { get; }
///
/// Gets the property info cache for faster lookups.
///
protected Dictionary PropertyCache { get; }
///
/// Initializes a new instance of the class.
///
/// An instance of the compiler generated object.
public CompilerGeneratedObjectWrapper(object generatedObject)
{
GeneratedObject = generatedObject;
GeneratedType = generatedObject.GetType();
PropertyCache = [];
}
///
/// Gets the value of a field in the compiler generated object.
///
/// The name of the field to get.
/// The type of the field.
/// >The value of the field.
/// Thrown if the field does not exist.
public TField GetField(string fieldName)
{
if (!PropertyCache.TryGetValue(fieldName, out var propertyInfo))
{
propertyInfo = AccessTools.Property(GeneratedType, fieldName);
if (propertyInfo == null)
{
throw new MissingMemberException($"Could not find field '{fieldName}' in type '{GeneratedType}'.");
}
PropertyCache[fieldName] = propertyInfo;
}
return (TField) propertyInfo.GetValue(GeneratedObject)!;
}
///
/// Sets the value of a field in the compiler generated object.
///
/// The name of the field to set.
/// The value to set.
/// The type of the field.
/// Thrown if the field does not exist.
public void SetField(string fieldName, TField value)
{
if (!PropertyCache.TryGetValue(fieldName, out var propertyInfo))
{
propertyInfo = AccessTools.Property(GeneratedType, fieldName);
if (propertyInfo == null)
{
throw new MissingMemberException($"Could not find field '{fieldName}' in type '{GeneratedType}'.");
}
PropertyCache[fieldName] = propertyInfo;
}
propertyInfo.SetValue(GeneratedObject, value);
}
}