Comments (1)
I just tried testing the different possible combinations of IsLiteral, IsInitOnly and IsStatic. At the same time I noticed that static readonly fields will also cause an exception:
FieldModifiers | IsLiteral | IsInitOnly | IsStatic | Causes Exception |
---|---|---|---|---|
False | False | False | No | |
readonly | False | True | False | No |
static | False | False | True | No |
static readonly | False | True | True | Yes |
const | True | False | True | Yes |
Updated Test class:
public class Test {
public const string MyConstField = "Don't set me";
public string MyField = "Set me";
public static string MyStaticField = "Set me";
public readonly string MyReadonlyField = "Set me";
public static readonly string MyStaticReadonlyField = "Don't set me";
}
MakeDeepCopy will throw for both MyStaticReadonlyField
and MyConstField
. Changing the Traverse.SetValue to the following seemed to work for my test case:
[HarmonyPatch]
public static class Patches {
[HarmonyPatch(typeof(Traverse), nameof(Traverse.SetValue)), HarmonyPrefix]
public static bool SetValue(object value, ref Traverse __result, Traverse __instance) {
var infoField = AccessTools.Field(typeof(Traverse), "_info");
var methodField = AccessTools.Field(typeof(Traverse), "_method");
var rootField = AccessTools.Field(typeof(Traverse), "_root");
var paramsField = AccessTools.Field(typeof(Traverse), "_params");
MemberInfo _info = infoField.GetValue(__instance) as MemberInfo;
MethodBase _method = methodField.GetValue(__instance) as MethodBase;
object[] _params = paramsField.GetValue(__instance) as object[];
object _root = rootField.GetValue(__instance);
if (_info is FieldInfo fi) {
bool isConst = fi.IsLiteral && !fi.IsInitOnly && fi.IsStatic;
bool isStaticReadonly = !fi.IsLiteral && fi.IsInitOnly && fi.IsStatic;
if (!isConst && !isStaticReadonly)
((FieldInfo)_info).SetValue(_root, value, AccessTools.all, null, CultureInfo.CurrentCulture);
}
if (_info is PropertyInfo)
((PropertyInfo)_info).SetValue(_root, value, AccessTools.all, null, _params, CultureInfo.CurrentCulture);
if (_method is not null)
throw new Exception($"cannot set value of method {_method.FullDescription()}");
__result = __instance;
return false;
}
}
Actually, is there a reason it tries to set static Fields at all?
While it works on normal static fields, does the method really need to set static fields which should be shared across instances anyway?
In total I see three different approaches:
- Check for
static readonly
orconst
as shown above and don't set those fields - Check for any
static
field and don't set those (depending on where Traverse.SetValue is used, this might not be a good idea)? - try/except System.FieldAccessException around the FieldInfo.SetValue call (this might be too broad in what it catches?)
Edit: To make sure this doesn't only apply to public string, I also tested for private int fields, which showed exactly the same behavior.
from harmony.
Related Issues (20)
- Hook exception: System.Exception: Cannot get result from void method System.Void HOT 2
- How to patch method of base class? HOT 1
- When applying a patch fails, the replacement's IL is not printed to the debug log HOT 2
- System.Exception: Parameter "xx" not found in method HOT 10
- SymbolExtensions does not resolve overriden method HOT 3
- can lib work in arm64? HOT 2
- Companion project promotion: Harmony Tools HOT 3
- PatchFunctions.UpdateWrapper NotImplementedException on MacOS HOT 11
- How do i change valuetype HOT 1
- Harmony.Patch() is a bit slow. HOT 2
- 'CORINFO_METHOD_INFO' from assembly 'System.Text.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'. HOT 4
- I try to hook DateTime.UtcNow but it throw exception HOT 5
- IL Compile Error when using PrefixFactory to provide a non-static Prefix method (Mono)
- x86 platform makes patch fail
- return type only support void and bool? why doesn't string work HOT 1
- Could not load type 'CORINFO_METHOD_INFO' from assembly 'System.Text.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'. HOT 6
- "ref" keyword not allowed for "__runOriginal" HOT 5
- HarmonyPatchAll do not work with multiple HarmonyPatch HOT 1
- UNITY_INCLUDE_TESTS causes harmony to not be included
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from harmony.