mirror of
https://github.com/Gurge44/EndlessHostRoles.git
synced 2026-10-20 11:39:54 +00:00
85 lines
3.0 KiB
C#
85 lines
3.0 KiB
C#
// 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;
|
|
|
|
/// <summary>
|
|
/// A safe wrapper around compiler generated classes like DisplayClass or IEnumerator state machines.
|
|
/// </summary>
|
|
public class CompilerGeneratedObjectWrapper
|
|
{
|
|
/// <summary>
|
|
/// Gets a reference to the compiler generated object.
|
|
/// </summary>
|
|
public object GeneratedObject { get; }
|
|
|
|
/// <summary>
|
|
/// Gets the type of the compiler generated object.
|
|
/// </summary>
|
|
protected Type GeneratedType { get; }
|
|
|
|
/// <summary>
|
|
/// Gets the property info cache for faster lookups.
|
|
/// </summary>
|
|
protected Dictionary<string, PropertyInfo> PropertyCache { get; }
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="CompilerGeneratedObjectWrapper"/> class.
|
|
/// </summary>
|
|
/// <param name="generatedObject">An instance of the compiler generated object.</param>
|
|
public CompilerGeneratedObjectWrapper(object generatedObject)
|
|
{
|
|
GeneratedObject = generatedObject;
|
|
GeneratedType = generatedObject.GetType();
|
|
|
|
PropertyCache = [];
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the value of a field in the compiler generated object.
|
|
/// </summary>
|
|
/// <param name="fieldName">The name of the field to get.</param>
|
|
/// <typeparam name="TField">The type of the field.</typeparam>
|
|
/// <returns>>The value of the field.</returns>
|
|
/// <exception cref="MissingMemberException">Thrown if the field does not exist.</exception>
|
|
public TField GetField<TField>(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)!;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets the value of a field in the compiler generated object.
|
|
/// </summary>
|
|
/// <param name="fieldName">The name of the field to set.</param>
|
|
/// <param name="value">The value to set.</param>
|
|
/// <typeparam name="TField">The type of the field.</typeparam>
|
|
/// <exception cref="MissingMemberException">Thrown if the field does not exist.</exception>
|
|
public void SetField<TField>(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);
|
|
}
|
|
} |