// general sorting by (in that order): before, after, priority and index public static int PriorityComparer(object obj, int index, int priority, string[] before, string[] after) { var trv = Traverse.Create(obj); var theirOwner = trv.Field("owner").GetValue <string>(); var theirPriority = trv.Field("priority").GetValue <int>(); var theirIndex = trv.Field("index").GetValue <int>(); if (before != null && Array.IndexOf(before, theirOwner) > -1) { return(-1); } if (after != null && Array.IndexOf(after, theirOwner) > -1) { return(1); } if (priority != theirPriority) { return(-(priority.CompareTo(theirPriority))); } return(index.CompareTo(theirIndex)); }
public static IEnumerable <CodeInstruction> ConvertToOurInstructions(IEnumerable instructions, List <object> originalInstructions, Dictionary <object, Dictionary <string, object> > unassignedValues) { var result = new List <CodeInstruction>(); var newInstructions = instructions.Cast <object>().ToList(); var index = -1; foreach (var op in newInstructions) { index++; var elementTo = new CodeInstruction(OpCodes.Nop, null); Traverse.IterateFields(op, elementTo, (name, trvFrom, trvDest) => { var val = trvFrom.GetValue(); if (name == nameof(ILInstruction.blocks)) { val = ConvertBlocks(val, trvDest.GetValueType()); } trvDest.SetValue(val); }); if (unassignedValues.TryGetValue(op, out var fields)) { var addExceptionInfo = ShouldAddExceptionInfo(op, index, originalInstructions, newInstructions, unassignedValues); var trv = Traverse.Create(elementTo); foreach (var field in fields) { if (addExceptionInfo || field.Key != nameof(CodeInstruction.blocks)) { trv.Field(field.Key).SetValue(field.Value); } } } yield return(elementTo); } }
public static HarmonyMethod Merge(List <HarmonyMethod> attributes) { var result = new HarmonyMethod(); if (attributes == null) { return(result); } var resultTrv = Traverse.Create(result); attributes.ForEach(attribute => { var trv = Traverse.Create(attribute); HarmonyFields().ForEach(f => { var val = trv.Field(f).GetValue(); if (val != null) { resultTrv.Field(f).SetValue(val); } }); }); return(result); }
public Traverse(Traverse traverse) { this.traverse = traverse; }
/// <summary>Makes a deep copy of any object</summary> /// <param name="source">The original object</param> /// <param name="resultType">The type of the instance that should be created</param> /// <param name="processor">Optional value transformation function (taking a field name and src/dst traverse objects)</param> /// <param name="pathRoot">The optional path root to start with</param> /// <returns>The copy of the original object</returns> /// public static object MakeDeepCopy(object source, Type resultType, Func <string, Traverse, Traverse, object> processor = null, string pathRoot = "") { if (source == null) { return(null); } var type = source.GetType(); if (type.IsPrimitive) { return(source); } if (type.IsEnum) { return(Enum.ToObject(resultType, (int)source)); } if (type.IsGenericType && resultType.IsGenericType) { var addOperation = FirstMethod(resultType, m => m.Name == "Add" && m.GetParameters().Count() == 1); if (addOperation != null) { var addableResult = Activator.CreateInstance(resultType); var addInvoker = MethodInvoker.GetHandler(addOperation); var newElementType = resultType.GetGenericArguments()[0]; var i = 0; foreach (var element in source as IEnumerable) { var iStr = (i++).ToString(); var path = pathRoot.Length > 0 ? pathRoot + "." + iStr : iStr; var newElement = MakeDeepCopy(element, newElementType, processor, path); addInvoker(addableResult, new object[] { newElement }); } return(addableResult); } // TODO: add dictionaries support // maybe use methods in Dictionary<KeyValuePair<TKey,TVal>> } if (type.IsArray && resultType.IsArray) { var elementType = resultType.GetElementType(); var length = ((Array)source).Length; var arrayResult = Activator.CreateInstance(resultType, new object[] { length }) as object[]; var originalArray = source as object[]; for (var i = 0; i < length; i++) { var iStr = i.ToString(); var path = pathRoot.Length > 0 ? pathRoot + "." + iStr : iStr; arrayResult[i] = MakeDeepCopy(originalArray[i], elementType, processor, path); } return(arrayResult); } var ns = type.Namespace; if (ns == "System" || (ns?.StartsWith("System.") ?? false)) { return(source); } var result = CreateInstance(resultType); Traverse.IterateFields(source, result, (name, src, dst) => { var path = pathRoot.Length > 0 ? pathRoot + "." + name : name; var value = processor != null ? processor(path, src, dst) : src.GetValue(); dst.SetValue(MakeDeepCopy(value, dst.GetValueType(), processor, path)); }); return(result); }
public Traverse(Traverse traverse) { }