List <MethodBase> GetBulkMethods() { var isPatchAll = containerType.GetCustomAttributes(true).Any(a => a.GetType().FullName == typeof(HarmonyPatchAll).FullName); if (isPatchAll) { var type = containerAttributes.declaringType; if (type == null) { throw new ArgumentException($"Using {typeof(HarmonyPatchAll).FullName} requires an additional attribute for specifying the Class/Type"); } var list = new List <MethodBase>(); list.AddRange(AccessTools.GetDeclaredConstructors(type).Cast <MethodBase>()); list.AddRange(AccessTools.GetDeclaredMethods(type).Cast <MethodBase>()); var props = AccessTools.GetDeclaredProperties(type); list.AddRange(props.Select(prop => prop.GetGetMethod(true)).Where(method => method != null).Cast <MethodBase>()); list.AddRange(props.Select(prop => prop.GetSetMethod(true)).Where(method => method != null).Cast <MethodBase>()); return(list); } string FailOnResult(IEnumerable <MethodBase> res) { if (res == null) { return("null"); } if (res.Any(m => m == null)) { return("some element was null"); } return(null); } var targetMethods = RunMethod <HarmonyTargetMethods, IEnumerable <MethodBase> >(null, null, FailOnResult); if (targetMethods != null) { return(targetMethods.ToList()); } var result = new List <MethodBase>(); var targetMethod = RunMethod <HarmonyTargetMethod, MethodBase>(null, null, method => method == null ? "null" : null); if (targetMethod != null) { result.Add(targetMethod); } return(result); }
List <MethodBase> GetBulkMethods() { var isPatchAll = containerType.GetCustomAttributes(true).Any(a => a.GetType().FullName == typeof(HarmonyPatchAll).FullName); if (isPatchAll) { var type = containerAttributes.declaringType; if (type is null) { throw new ArgumentException($"Using {typeof(HarmonyPatchAll).FullName} requires an additional attribute for specifying the Class/Type"); } var list = new List <MethodBase>(); list.AddRange(AccessTools.GetDeclaredConstructors(type).Cast <MethodBase>()); list.AddRange(AccessTools.GetDeclaredMethods(type).Cast <MethodBase>()); var props = AccessTools.GetDeclaredProperties(type); list.AddRange(props.Select(prop => prop.GetGetMethod(true)).Where(method => method is object).Cast <MethodBase>()); list.AddRange(props.Select(prop => prop.GetSetMethod(true)).Where(method => method is object).Cast <MethodBase>()); return(list); }
void PrepareType() { var mainPrepareResult = RunMethod <HarmonyPrepare, bool>(true); if (mainPrepareResult == false) { return; } var customOriginals = RunMethod <HarmonyTargetMethods, IEnumerable <MethodBase> >(null); if (customOriginals != null) { originals.Clear(); originals.AddRange(customOriginals); } else { var originalMethodType = containerAttributes.methodType; // MethodType default is Normal if (containerAttributes.methodType == null) { containerAttributes.methodType = MethodType.Normal; } var isPatchAll = container.GetCustomAttributes(true).Any(a => a.GetType().FullName == typeof(HarmonyPatchAll).FullName); if (isPatchAll) { var type = containerAttributes.declaringType; originals.AddRange(AccessTools.GetDeclaredConstructors(type).Cast <MethodBase>()); originals.AddRange(AccessTools.GetDeclaredMethods(type).Cast <MethodBase>()); var props = AccessTools.GetDeclaredProperties(type); originals.AddRange(props.Select(prop => prop.GetGetMethod(true)).Where(method => method != null).Cast <MethodBase>()); originals.AddRange(props.Select(prop => prop.GetSetMethod(true)).Where(method => method != null).Cast <MethodBase>()); } else { var original = RunMethod <HarmonyTargetMethod, MethodBase>(null); if (original == null) { original = GetOriginalMethod(); } if (original == null) { var info = "("; info += "declaringType=" + containerAttributes.declaringType + ", "; info += "methodName =" + containerAttributes.methodName + ", "; info += "methodType=" + originalMethodType + ", "; info += "argumentTypes=" + containerAttributes.argumentTypes.Description(); info += ")"; throw new ArgumentException("No target method specified for class " + container.FullName + " " + info); } originals.Add(original); } } PatchTools.GetPatches(container, out var prefixMethod, out var postfixMethod, out var transpilerMethod, out var finalizerMethod); if (prefix != null) { prefix.method = prefixMethod; } if (postfix != null) { postfix.method = postfixMethod; } if (transpiler != null) { transpiler.method = transpilerMethod; } if (finalizer != null) { finalizer.method = finalizerMethod; } if (prefixMethod != null) { if (prefixMethod.IsStatic == false) { throw new ArgumentException("Patch method " + prefixMethod.FullDescription() + " must be static"); } var prefixAttributes = HarmonyMethodExtensions.GetFromMethod(prefixMethod); containerAttributes.Merge(HarmonyMethod.Merge(prefixAttributes)).CopyTo(prefix); } if (postfixMethod != null) { if (postfixMethod.IsStatic == false) { throw new ArgumentException("Patch method " + postfixMethod.FullDescription() + " must be static"); } var postfixAttributes = HarmonyMethodExtensions.GetFromMethod(postfixMethod); containerAttributes.Merge(HarmonyMethod.Merge(postfixAttributes)).CopyTo(postfix); } if (transpilerMethod != null) { if (transpilerMethod.IsStatic == false) { throw new ArgumentException("Patch method " + transpilerMethod.FullDescription() + " must be static"); } var transpilerAttributes = HarmonyMethodExtensions.GetFromMethod(transpilerMethod); containerAttributes.Merge(HarmonyMethod.Merge(transpilerAttributes)).CopyTo(transpiler); } if (finalizerMethod != null) { if (finalizerMethod.IsStatic == false) { throw new ArgumentException("Patch method " + finalizerMethod.FullDescription() + " must be static"); } var finalizerAttributes = HarmonyMethodExtensions.GetFromMethod(finalizerMethod); containerAttributes.Merge(HarmonyMethod.Merge(finalizerAttributes)).CopyTo(finalizer); } }
private void PrepareType() { var mainPrepareResult = RunMethod <HarmonyPrepare, bool>(true); if (mainPrepareResult == false) { return; } var originalMethodType = containerAttributes.methodType; // MethodType default is Normal if (containerAttributes.methodType == null) { containerAttributes.methodType = MethodType.Normal; } var reversePatchAttr = typeof(HarmonyReversePatch).FullName; var reversePatchMethods = container.GetMethods(AccessTools.all).Where(m => m.GetCustomAttributes(true).Any(a => a.GetType().FullName == reversePatchAttr)).ToList(); foreach (var reversePatchMethod in reversePatchMethods) { var attr = containerAttributes.Merge(new HarmonyMethod(reversePatchMethod)); var originalMethod = GetOriginalMethod(attr); var reversePatcher = instance.CreateReversePatcher(originalMethod, reversePatchMethod); reversePatcher.Patch(); } var customOriginals = RunMethod <HarmonyTargetMethods, IEnumerable <MethodBase> >(null); if (customOriginals != null) { originals.Clear(); originals.AddRange(customOriginals); } else { var isPatchAll = container.GetCustomAttributes(true).Any(a => a.GetType().FullName == typeof(HarmonyPatchAll).FullName); if (isPatchAll) { var type = containerAttributes.declaringType; originals.AddRange(AccessTools.GetDeclaredConstructors(type).Cast <MethodBase>()); originals.AddRange(AccessTools.GetDeclaredMethods(type).Cast <MethodBase>()); var props = AccessTools.GetDeclaredProperties(type); originals.AddRange(props.Select(prop => prop.GetGetMethod(true)).Where(method => method != null) .Cast <MethodBase>()); originals.AddRange(props.Select(prop => prop.GetSetMethod(true)).Where(method => method != null) .Cast <MethodBase>()); } else { var original = RunMethod <HarmonyTargetMethod, MethodBase>(null) ?? GetOriginalMethod(containerAttributes); if (original == null) { var info = "("; info += $"declaringType={containerAttributes.declaringType}, "; info += $"methodName ={containerAttributes.methodName}, "; info += $"methodType={originalMethodType}, "; info += $"argumentTypes={containerAttributes.argumentTypes.Description()}"; info += ")"; throw new ArgumentException( $"No target method specified for class {container.FullName} {info}"); } originals.Add(original); } } GetPatches(container, out var prefixMethod, out var postfixMethod, out var transpilerMethod, out var finalizerMethod); if (prefix != null) { prefix.method = prefixMethod; } if (postfix != null) { postfix.method = postfixMethod; } if (transpiler != null) { transpiler.method = transpilerMethod; } if (finalizer != null) { finalizer.method = finalizerMethod; } if (prefixMethod != null) { if (prefixMethod.IsStatic == false) { throw new ArgumentException($"Patch method {prefixMethod.GetID()} must be static"); } var prefixAttributes = HarmonyMethodExtensions.GetFromMethod(prefixMethod); containerAttributes.Merge(HarmonyMethod.Merge(prefixAttributes)).CopyTo(prefix); } if (postfixMethod != null) { if (postfixMethod.IsStatic == false) { throw new ArgumentException($"Patch method {postfixMethod.GetID()} must be static"); } var postfixAttributes = HarmonyMethodExtensions.GetFromMethod(postfixMethod); containerAttributes.Merge(HarmonyMethod.Merge(postfixAttributes)).CopyTo(postfix); } if (transpilerMethod != null) { if (transpilerMethod.IsStatic == false) { throw new ArgumentException($"Patch method {transpilerMethod.GetID()} must be static"); } var transpilerAttributes = HarmonyMethodExtensions.GetFromMethod(transpilerMethod); containerAttributes.Merge(HarmonyMethod.Merge(transpilerAttributes)).CopyTo(transpiler); } if (finalizerMethod != null) { if (finalizerMethod.IsStatic == false) { throw new ArgumentException($"Patch method {finalizerMethod.GetID()} must be static"); } var finalizerAttributes = HarmonyMethodExtensions.GetFromMethod(finalizerMethod); containerAttributes.Merge(HarmonyMethod.Merge(finalizerAttributes)).CopyTo(finalizer); } }