Example #1
0
        private static void OnBeforeExpectedChange(this ValueAccess access, object target)
        {
            object value;

            if (BufferedChanges.ContainsKey(access) &&
                BufferedChanges[access].TryGetValue(target, out ValueChangeRequest cache))
            {
                value = cache.RequestedValue;
                access.Set(target, value);
            }
            else
            {
                value = access.Get(target);
            }

            ActiveFields.Push(new ValueData(access, target, value));
        }
Example #2
0
        private static void PopActiveFields()
        {
            while (ActiveFields.Count > 0)
            {
                ValueData data = ActiveFields.Pop();
                if (data == null)
                {
                    break; // The marker
                }

                ValueAccess field = data.Access;

                object newValue = data.Access.Get(data.Target);
                bool   changed  = !Equals(newValue, data.Value);

                Dictionary <object, ValueChangeRequest> fieldBuffer = BufferedChanges.Assert(field);
                if (fieldBuffer.TryGetValue(data.Target, out ValueChangeRequest cached))
                {
                    if (changed && cached.RequestProcessed)
                    {
                        cached.RequestProcessed = false;
                    }

                    cached.RequestedValue = newValue;
                    field.Set(data.Target, cached.LatestActualValue);
                    continue;
                }

                if (!changed)
                {
                    continue;
                }

                fieldBuffer[data.Target] = new ValueChangeRequest
                {
                    LatestActualValue = data.Value,
                    RequestedValue    = newValue
                };
                field.Set(data.Target, data.Value);
            }
        }
Example #3
0
 /// <summary>
 ///     During the execution of any of the <paramref name="triggers" /> methods, any change to the
 ///     value will not be applied but instead written to the change buffer
 ///     <see cref="BufferedChanges" />.
 /// </summary>
 /// <param name="value">Accessor to the value</param>
 /// <param name="triggers">
 ///     Trigger methods during which the changes to the value are written to the
 ///     buffer instead
 /// </param>
 /// <param name="condition">The buffer is only active if the condition evaluates to true</param>
 public static void Intercept(
     ValueAccess value,
     IEnumerable <MethodAccess> triggers,
     Func <bool> condition)
 {
     lock (Patcher.HarmonyLock)
     {
         foreach (MethodAccess method in triggers)
         {
             Patcher.HarmonyInstance.Patch(method.MemberInfo, PatchPrefix, PatchPostfix);
             method.SetGlobalHandler(
                 (instance, args) =>
             {
                 if (condition())
                 {
                     value.OnBeforeExpectedChange(instance);
                 }
             });
         }
     }
 }
Example #4
0
 public ValueData([NotNull] ValueAccess access, object target, object value)
 {
     Access = access;
     Target = target;
     Value  = value;
 }