GithubHelp home page GithubHelp logo

Comments (1)

xADDBx avatar xADDBx commented on September 27, 2024

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:
grafik

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 MyStaticReadonlyFieldand 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:

  1. Check for static readonly or const as shown above and don't set those fields
  2. Check for any static field and don't set those (depending on where Traverse.SetValue is used, this might not be a good idea)?
  3. 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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.