diff --git a/IPA.Loader/Utilities/Accessor.cs b/IPA.Loader/Utilities/Accessor.cs
index 67f7270a..6e79bf36 100644
--- a/IPA.Loader/Utilities/Accessor.cs
+++ b/IPA.Loader/Utilities/Accessor.cs
@@ -134,13 +134,13 @@ namespace IPA.Utilities
///
/// the object it is a member of
/// the value of the property
- public delegate U Getter(T obj);
+ public delegate U Getter(ref T obj);
///
/// A setter for a property.
///
/// the object it is a member of
/// the new property value
- public delegate void Setter(T obj, U val);
+ public delegate void Setter(ref T obj, U val);
private static readonly Dictionary props = new Dictionary();
@@ -154,10 +154,40 @@ namespace IPA.Utilities
var setM = prop.GetSetMethod(true);
Getter getter = null;
Setter setter = null;
- if (getM != null)
- getter = (Getter)Delegate.CreateDelegate(typeof(Getter), getM);
- if (setM != null)
- setter = (Setter)Delegate.CreateDelegate(typeof(Setter), setM);
+
+ if (typeof(T).IsValueType)
+ {
+ if (getM != null)
+ getter = (Getter)Delegate.CreateDelegate(typeof(Getter), getM);
+ if (setM != null)
+ setter = (Setter)Delegate.CreateDelegate(typeof(Setter), setM);
+ }
+ else
+ {
+ if (getM != null)
+ {
+ var dyn = new DynamicMethod($"<>_get__{propName}", typeof(U), new[] { typeof(T).MakeByRefType() }, typeof(PropertyAccessor), true);
+ var il = dyn.GetILGenerator();
+ il.Emit(OpCodes.Ldarg_0);
+ il.Emit(OpCodes.Ldind_Ref);
+ il.Emit(OpCodes.Tailcall);
+ il.Emit(getM.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, getM);
+ il.Emit(OpCodes.Ret);
+ getter = (Getter)dyn.CreateDelegate(typeof(Getter));
+ }
+ if (setM != null)
+ {
+ var dyn = new DynamicMethod($"<>_set__{propName}", typeof(void), new[] { typeof(T).MakeByRefType(), typeof(U) }, typeof(PropertyAccessor), true);
+ var il = dyn.GetILGenerator();
+ il.Emit(OpCodes.Ldarg_0);
+ il.Emit(OpCodes.Ldind_Ref);
+ il.Emit(OpCodes.Ldarg_1);
+ il.Emit(OpCodes.Tailcall);
+ il.Emit(setM.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, setM);
+ il.Emit(OpCodes.Ret);
+ setter = (Setter)dyn.CreateDelegate(typeof(Setter));
+ }
+ }
return (getter, setter);
}
@@ -197,7 +227,7 @@ namespace IPA.Utilities
/// when the property does not exist
///
///
- public static U Get(ref T obj, string name) => GetGetter(name)(obj);
+ public static U Get(ref T obj, string name) => GetGetter(name)(ref obj);
///
/// Gets the value of the property identified by on .
///
@@ -207,7 +237,7 @@ namespace IPA.Utilities
/// when the property does not exist
///
///
- public static U Get(T obj, string name) => GetGetter(name)(obj);
+ public static U Get(T obj, string name) => GetGetter(name)(ref obj);
///
/// Sets the value of the property identified by on .
///
@@ -220,7 +250,7 @@ namespace IPA.Utilities
/// when the property does not exist
///
///
- public static void Set(ref T obj, string name, U val) => GetSetter(name)(obj, val);
+ public static void Set(ref T obj, string name, U val) => GetSetter(name)(ref obj, val);
///
/// Sets the value of the property identified by on .
///
@@ -233,6 +263,6 @@ namespace IPA.Utilities
/// when the property does not exist
///
///
- public static void Set(T obj, string name, U val) => GetSetter(name)(obj, val);
+ public static void Set(T obj, string name, U val) => GetSetter(name)(ref obj, val);
}
}