diff --git a/Harmony/Tools/AccessTools.cs b/Harmony/Tools/AccessTools.cs index 32b1871a..ba05cd73 100644 --- a/Harmony/Tools/AccessTools.cs +++ b/Harmony/Tools/AccessTools.cs @@ -1994,7 +1994,8 @@ public static object MakeDeepCopy(object source, Type resultType, Func 0 ? pathRoot + "." + name : name; var value = processor is not null ? processor(path, src, dst) : src.GetValue(); - _ = dst.SetValue(MakeDeepCopy(value, dst.GetValueType(), processor, path)); + if (dst.IsWriteable) + _ = dst.SetValue(MakeDeepCopy(value, dst.GetValueType(), processor, path)); }); return result; } diff --git a/Harmony/Tools/Traverse.cs b/Harmony/Tools/Traverse.cs index 2dbb0b4c..7726fcef 100644 --- a/Harmony/Tools/Traverse.cs +++ b/Harmony/Tools/Traverse.cs @@ -183,6 +183,35 @@ public Type GetValueType() return null; } + /// Checks if the current traverse instance is for a field + /// True if its a field + /// + public bool IsField => _info is FieldInfo; + + /// Checks if the current traverse instance is for a property + /// True if its a property + /// + public bool IsProperty => _info is PropertyInfo; + + /// Checks if the current field or property is writeable + /// True if writing is possible + /// + public bool IsWriteable + { + get + { + if (_info is FieldInfo fi) + { + var isConst = fi.IsLiteral && fi.IsInitOnly == false && fi.IsStatic; + var isStaticReadonly = fi.IsLiteral == false && fi.IsInitOnly && fi.IsStatic; + return isConst == false && isStaticReadonly == false; + } + if (_info is PropertyInfo pi) + return pi.CanWrite; + return false; + } + } + Traverse Resolve() { if (_root is null) @@ -407,7 +436,11 @@ public static void IterateProperties(object source, object target, ActionA default field action that copies fields to fields /// - public static Action CopyFields = (from, to) => { _ = to.SetValue(from.GetValue()); }; + public static Action CopyFields = (from, to) => + { + if (to.IsWriteable) + _ = to.SetValue(from.GetValue()); + }; /// Returns a string that represents the current traverse /// A string representation