/// <summary> /// Returns the "pretty" name of this <see cref="MemberInfo"/> (including the full type-name) /// and also return the member-type (if any) into <b>prefix</b> and method-parameters (if any) into <b>postfix</b> /// </summary> /// <param name="member">Type-member to get the name of</param> /// <param name="memberKind">Receives the member-kind, this member represents</param> /// <param name="prefix">Receives the field/property-type or method return-type</param> /// <param name="postfix">Receives the method-parameters, if this member is a method</param> /// <returns>The full name of this member or null if this member is compiler-generated</returns> /// <remarks> /// Properties and events in .NET are actually methods with a special naming-convention. /// (i.e. get_<b>Name</b> / set_<b>Name</b> for properties and add_<b>Name</b> / remove_<b>Name</b> for events) /// As we're not interested in these methods, but in the properties/events they represent, /// we detect these methods here and return the name of the property/event instead while setting <b>memberKind</b> accordingly /// </remarks> public static string GetPrettyName(this MemberInfo member, out SymbolKind memberKind, out string prefix, out string postfix) { memberKind = SymbolKind.SYMBOL_FIELD; prefix = ""; postfix = ""; if (member.Name.Contains("<") || member.IsMemberOfCompilerGeneratedClass()) // compiler-generated { return(null); } if (member is ConstructorInfo ctor) { memberKind = SymbolKind.SYMBOL_METHOD; prefix = ctor.GetModifiers(); if (ctor.IsGenericMethod) { postfix += "<" + string.Join(", ", ctor.GetGenericArguments() .Select(a => NameHelper.TranslateTypeName(a, true))) + ">"; } postfix += SerializeParameters(ctor.GetParameters()); return(ctor.DeclaringType.GetPrettyName() + ctor.Name); } if (member is MethodInfo method) { // method generated by compiler (i.e. lambdas) ? var match = rxInternName.Match(method.Name); if (match.Success) { if (member.DeclaringType.DeclaringType != null) { Debug.Assert(false, "Checkme"); } var name = match.Groups["name"].Value; // map getter/setter to correct property/event if (IsPropertyOrEventMethod(method, name, out prefix, out string propertyOrEventName)) { return(method.DeclaringType.GetPrettyName() + "." + propertyOrEventName); } else { foreach (var meth in method.DeclaringType.GetMethods(flags)) { if (meth.Name == name) { if (meth.DeclaringType.Name.Contains("<")) { Debug.Assert(false, "Checkme"); } memberKind = SymbolKind.SYMBOL_METHOD; prefix = meth.GetModifiers() + meth.ReturnType.GetPrettyName(); return(meth.DeclaringType.GetPrettyName() + "." + meth.Name); } } Debug.Assert(false, "Method not found"); } } else { // regular method var name = method.Name; // map getter/setter to correct property/event if (IsPropertyOrEventMethod(method, name, out prefix, out string propertyOrEventName)) { return(method.DeclaringType.GetPrettyName() + "." + propertyOrEventName); } else { memberKind = SymbolKind.SYMBOL_METHOD; prefix = method.GetModifiers() + NameHelper.TranslateTypeName(method.ReturnType); if (method.IsGenericMethod) { postfix += "<" + string.Join(", ", method.GetGenericArguments().Select(a => NameHelper.TranslateTypeName(a, true))) + ">"; } postfix += SerializeParameters(method.GetParameters()); return(method.DeclaringType.GetPrettyName() + "." + method.Name); } } } else if (member is PropertyInfo property) { if (member.DeclaringType.Name.Contains("<")) { return(null); } prefix = property.GetModifiers() + property.PropertyType.GetPrettyName(); return(property.DeclaringType.GetPrettyName() + "." + property.Name); } else if (member is FieldInfo field) { // ignore auto-generated backing fields for properties if (member.DeclaringType.Name.Contains("<") || field.Name.StartsWith("<")) { return(null); } prefix = field.GetModifiers() + field.FieldType.GetPrettyName(); return(field.DeclaringType.GetPrettyName() + "." + field.Name); } else if (member is EventInfo eventInfo) { if (member.DeclaringType.Name.Contains("<")) { return(null); } prefix = eventInfo.GetModifiers() + eventInfo.EventHandlerType.GetPrettyName(); return(eventInfo.DeclaringType.GetPrettyName() + "." + eventInfo.Name); } else if (member is TypeInfo nestedType) { if (nestedType.Name.Contains("<")) { return(null); } memberKind = SymbolKind.SYMBOL_CLASS; return(nestedType.DeclaringType.GetPrettyName() + "." + nestedType.Name); } return(null); }
/// <summary> /// Returns the "pretty" name of this <see cref="Type"/> /// </summary> public static string GetPrettyName(this Type type) { return(NameHelper.TranslateTypeName(type)); }