//----------------------------------------------------------------------- // // Copyright (c) 2018 Sirenix IVS // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //----------------------------------------------------------------------- namespace VRC.Udon.Serialization.OdinSerializer.Utilities { using System; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; /// /// Various extensions for MethodInfo. /// public static class MethodInfoExtensions { /// /// Returns the specified method's full name "methodName(argType1 arg1, argType2 arg2, etc)" /// Uses the specified gauntlet to replaces type names, ex: "int" instead of "Int32" /// public static string GetFullName(this MethodBase method, string extensionMethodPrefix) { var builder = new StringBuilder(); bool isExtensionMethod = method.IsExtensionMethod(); if (isExtensionMethod) { builder.Append(extensionMethodPrefix); } builder.Append(method.Name); builder.Append("("); builder.Append(method.GetParamsNames()); builder.Append(")"); return builder.ToString(); } /// /// Returns a string representing the passed method parameters names. Ex "int num, float damage, Transform target" /// public static string GetParamsNames(this MethodBase method) { ParameterInfo[] pinfos = method.IsExtensionMethod() ? method.GetParameters().Skip(1).ToArray() : method.GetParameters(); var builder = new StringBuilder(); for (int i = 0, len = pinfos.Length; i < len; i++) { var param = pinfos[i]; var paramTypeName = param.ParameterType.GetNiceName(); builder.Append(paramTypeName); builder.Append(" "); builder.Append(param.Name); if (i < len - 1) { builder.Append(", "); } } return builder.ToString(); } /// /// Returns the specified method's full name. /// public static string GetFullName(this MethodBase method) { return GetFullName(method, "[ext] "); } /// /// Tests if a method is an extension method. /// public static bool IsExtensionMethod(this MethodBase method) { var type = method.DeclaringType; return type.IsSealed && !type.IsGenericType && !type.IsNested && method.IsDefined(typeof(ExtensionAttribute), false); } /// /// Determines whether the specified method is an alias. /// /// The method to check. /// /// true if the specified method is an alias; otherwise, false. /// public static bool IsAliasMethod(this MethodInfo methodInfo) { return methodInfo is MemberAliasMethodInfo; } /// /// Returns the original, backing method of an alias method if the method is an alias. /// /// The method to check. /// /// if set to true an exception will be thrown if the method is not aliased. /// /// The method was not aliased; this only occurs if throwOnNotAliased is true. public static MethodInfo DeAliasMethod(this MethodInfo methodInfo, bool throwOnNotAliased = false) { MemberAliasMethodInfo aliasMethodInfo = methodInfo as MemberAliasMethodInfo; if (aliasMethodInfo != null) { while (aliasMethodInfo.AliasedMethod is MemberAliasMethodInfo) { aliasMethodInfo = aliasMethodInfo.AliasedMethod as MemberAliasMethodInfo; } return aliasMethodInfo.AliasedMethod; } if (throwOnNotAliased) { throw new ArgumentException("The method " + methodInfo.GetNiceName() + " was not aliased."); } return methodInfo; } } }