Beispiel #1
0
        internal static MethodBase GetOriginalMethod(this HarmonyMethod attr)
        {
            try
            {
                switch (attr.methodType)
                {
                case MethodType.Normal:
                    if (attr.methodName is null)
                    {
                        return(null);
                    }
                    return(AccessTools.DeclaredMethod(attr.declaringType, attr.methodName, attr.argumentTypes));

                case MethodType.Getter:
                    if (attr.methodName is null)
                    {
                        return(null);
                    }
                    return(AccessTools.DeclaredProperty(attr.declaringType, attr.methodName).GetGetMethod(true));

                case MethodType.Setter:
                    if (attr.methodName is null)
                    {
                        return(null);
                    }
                    return(AccessTools.DeclaredProperty(attr.declaringType, attr.methodName).GetSetMethod(true));

                case MethodType.Constructor:
                    return(AccessTools.DeclaredConstructor(attr.declaringType, attr.argumentTypes));

                case MethodType.StaticConstructor:
                    return(AccessTools.GetDeclaredConstructors(attr.declaringType)
                           .Where(c => c.IsStatic)
                           .FirstOrDefault());

                case MethodType.Enumerator:
                    if (attr.methodName is null)
                    {
                        return(null);
                    }
                    var method = AccessTools.DeclaredMethod(attr.declaringType, attr.methodName, attr.argumentTypes);
                    return(AccessTools.EnumeratorMoveNext(method));
                }
            }
            catch (AmbiguousMatchException ex)
            {
                throw new HarmonyException($"Ambiguous match for HarmonyMethod[{attr.Description()}]", ex.InnerException ?? ex);
            }

            return(null);
        }
Beispiel #2
0
 internal PropertyInfo GetPropertyInfo(Type type, string name)
 {
     if (properties.TryGetValue(type, out var propertiesByType) == false)
     {
         propertiesByType = new Dictionary <string, PropertyInfo>();
         properties.Add(type, propertiesByType);
     }
     if (propertiesByType.TryGetValue(name, out var property) == false)
     {
         property = AccessTools.DeclaredProperty(type, name);
         propertiesByType.Add(name, property);
     }
     return(property);
 }
Beispiel #3
0
        MethodBase GetOriginalMethod()
        {
            var attr = containerAttributes;

            if (attr.declaringType == null)
            {
                return(null);
            }

            switch (attr.methodType)
            {
            case MethodType.Normal:
                if (attr.methodName == null)
                {
                    return(null);
                }
                return(AccessTools.DeclaredMethod(attr.declaringType, attr.methodName, attr.argumentTypes));

            case MethodType.Getter:
                if (attr.methodName == null)
                {
                    return(null);
                }
                return(AccessTools.DeclaredProperty(attr.declaringType, attr.methodName).GetGetMethod(true));

            case MethodType.Setter:
                if (attr.methodName == null)
                {
                    return(null);
                }
                return(AccessTools.DeclaredProperty(attr.declaringType, attr.methodName).GetSetMethod(true));

            case MethodType.Constructor:
                return(AccessTools.DeclaredConstructor(attr.declaringType, attr.argumentTypes));

            case MethodType.StaticConstructor:
                return(AccessTools.GetDeclaredConstructors(attr.declaringType)
                       .Where(c => c.IsStatic)
                       .FirstOrDefault());
            }

            return(null);
        }
Beispiel #4
0
        internal static MethodBase GetOriginalMethod(this HarmonyMethod attr)
        {
            switch (attr.methodType)
            {
            case MethodType.Normal:
                if (attr.methodName == null)
                {
                    return(null);
                }
                return(AccessTools.DeclaredMethod(attr.declaringType, attr.methodName, attr.argumentTypes));

            case MethodType.Getter:
                if (attr.methodName == null)
                {
                    return(null);
                }
                return(AccessTools.DeclaredProperty(attr.declaringType, attr.methodName).GetGetMethod(true));

            case MethodType.Setter:
                if (attr.methodName == null)
                {
                    return(null);
                }
                return(AccessTools.DeclaredProperty(attr.declaringType, attr.methodName).GetSetMethod(true));

            case MethodType.Constructor:
                return(AccessTools.DeclaredConstructor(attr.declaringType, attr.argumentTypes));

            case MethodType.StaticConstructor:
                return(AccessTools.GetDeclaredConstructors(attr.declaringType)
                       .Where(c => c.IsStatic)
                       .FirstOrDefault());
            }

            return(null);
        }
        /// <summary>
        /// Get the member specified by the <paramref name="attribute"/>. Throws if the member was not found.
        /// </summary>
        /// <exception cref="ArgumentException">Thrown if the member described in the <paramref name="attribute"/> couldn't be found.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="attribute"/> is <see langword="null"/></exception>
        internal static MethodBase GetOriginalMethod(HarmonyMethod attribute)
        {
            if (attribute == null)
            {
                throw new ArgumentNullException(nameof(attribute));
            }

            string GetPatchName()
            {
                return(attribute.method?.FullDescription() ?? "Unknown patch");
            }

            MethodBase MakeFailure(string reason)
            {
                Logger.Log(Logger.LogChannel.Error, () => $"Failed to process patch {GetPatchName()} - {reason}");
                return(null);
            }

            if (attribute.declaringType == null)
            {
                return(MakeFailure("declaringType cannot be null"));
            }

            switch (attribute.methodType)
            {
            case MethodType.Normal:
            {
                if (string.IsNullOrEmpty(attribute.methodName))
                {
                    return(MakeFailure("methodName can't be empty"));
                }

                if (attribute.methodName == ".ctor")
                {
                    Logger.LogText(Logger.LogChannel.Warn, GetPatchName() + " - MethodType.Constructor should be used instead of setting methodName to .ctor");
                    goto case MethodType.Constructor;
                }
                if (attribute.methodName == ".cctor")
                {
                    Logger.LogText(Logger.LogChannel.Warn, GetPatchName() + " - MethodType.StaticConstructor should be used instead of setting methodName to .cctor");
                    goto case MethodType.StaticConstructor;
                }

                if (attribute.methodName.StartsWith("get_") || attribute.methodName.StartsWith("set_"))
                {
                    Logger.LogText(Logger.LogChannel.Warn, GetPatchName() + " - MethodType.Getter and MethodType.Setter should be used instead adding get_ and set_ to property names");
                }

                var result = AccessTools.DeclaredMethod(attribute.declaringType, attribute.methodName, attribute.argumentTypes);
                if (result != null)
                {
                    return(result);
                }

                result = AccessTools.Method(attribute.declaringType, attribute.methodName, attribute.argumentTypes);
                if (result != null)
                {
                    Logger.LogText(Logger.LogChannel.Warn, GetPatchName() + $" - Could not find method {attribute.methodName} with {attribute.argumentTypes?.Length ?? 0} parameters in type {attribute.declaringType.FullDescription()}, but it was found in base class of this type {result.DeclaringType.FullDescription()}");
                    return(result);
                }

                return(MakeFailure($"Could not find method {attribute.methodName} with {attribute.argumentTypes.Description()} parameters in type {attribute.declaringType.FullDescription()}"));
            }

            case MethodType.Getter:
            {
                if (string.IsNullOrEmpty(attribute.methodName))
                {
                    return(MakeFailure("methodName can't be empty"));
                }

                var result = AccessTools.DeclaredProperty(attribute.declaringType, attribute.methodName);
                if (result != null)
                {
                    var getter = result.GetGetMethod(true);
                    if (getter == null)
                    {
                        return(MakeFailure($"Property {attribute.methodName} does not have a Getter"));
                    }
                    return(getter);
                }

                result = AccessTools.Property(attribute.declaringType, attribute.methodName);
                if (result != null)
                {
                    Logger.LogText(Logger.LogChannel.Warn, GetPatchName() + $" - Could not find property {attribute.methodName} in type {attribute.declaringType.FullDescription()}, but it was found in base class of this type: {result.DeclaringType.FullDescription()}");
                    var getter = result.GetGetMethod(true);
                    if (getter == null)
                    {
                        return(MakeFailure($"Property {attribute.methodName} does not have a Getter"));
                    }
                    return(getter);
                }

                return(MakeFailure($"Could not find property {attribute.methodName} in type {attribute.declaringType.FullDescription()}"));
            }

            case MethodType.Setter:
            {
                if (string.IsNullOrEmpty(attribute.methodName))
                {
                    return(MakeFailure("methodName can't be empty"));
                }

                var result = AccessTools.DeclaredProperty(attribute.declaringType, attribute.methodName);
                if (result != null)
                {
                    var getter = result.GetSetMethod(true);
                    if (getter == null)
                    {
                        return(MakeFailure($"Property {attribute.methodName} does not have a Setter"));
                    }
                    return(getter);
                }

                result = AccessTools.Property(attribute.declaringType, attribute.methodName);
                if (result != null)
                {
                    Logger.LogText(Logger.LogChannel.Warn, GetPatchName() + $" - Could not find property {attribute.methodName} in type {attribute.declaringType.FullDescription()}, but it was found in base class of this type: {result.DeclaringType.FullDescription()}");
                    var getter = result.GetSetMethod(true);
                    if (getter == null)
                    {
                        return(MakeFailure($"Property {attribute.methodName} does not have a Setter"));
                    }
                    return(getter);
                }

                return(MakeFailure($"Could not find property {attribute.methodName} in type {attribute.declaringType.FullDescription()}"));
            }

            case MethodType.Constructor:
            {
                var constructor = AccessTools.DeclaredConstructor(attribute.declaringType, attribute.argumentTypes);
                if (constructor != null)
                {
                    return(constructor);
                }

                return(MakeFailure($"Could not find constructor with {attribute.argumentTypes.Description()} parameters in type {attribute.declaringType.FullDescription()}"));
            }

            case MethodType.StaticConstructor:
            {
                var constructor = AccessTools.GetDeclaredConstructors(attribute.declaringType).FirstOrDefault(c => c.IsStatic);
                if (constructor != null)
                {
                    return(constructor);
                }

                return(MakeFailure($"Could not find static constructor in type {attribute.declaringType.FullDescription()}"));
            }

            default:
                throw new ArgumentOutOfRangeException(nameof(attribute.methodType), attribute.methodType, "Unknown method type");
            }
        }