2009-08-21 14 views
25

Gibt es vorhandene Funktionalität in der .NET BCL, um die vollständige Signatur einer Methode zur Laufzeit (wie Sie in den Visual Studio ObjectBrowser - einschließlich Parameternamen) mit zu drucken Informationen von MethodInfo verfügbar?Drucken vollständige Signatur einer Methode aus einer MethodInfo

So zum Beispiel, wenn Sie String.Compare nachschlagen() eine der Überlastungen würde drucken, wie:

public static int Compare(string strA, int indexA, string strB, int indexB, int length, bool ignoreCase, System.Globalization.CultureInfo culture) 

Beachten Sie die Anwesenheit der vollständigen Signatur mit allen Zugangs- und Umfang Qualifier sowie eine komplette Liste der Parameter einschließlich Namen. Das ist, was ich suche. Ich könnte meine eigene Methode schreiben, aber ich würde lieber eine vorhandene Implementierung verwenden, wenn möglich.

Antwort

24

Leider glaube ich nicht, dass es eine eingebaute Methode gibt, die das tun würde. Ihr am besten wäre eine eigene Signatur zu erstellen, indem der Method Klasse untersuchen

EDIT: Ich habe gerade dieses

MethodBase mi = MethodInfo.GetCurrentMethod(); 
mi.ToString(); 

und Sie erhalten

Void Main (System.String [ ])

Dies ist möglicherweise nicht das, was Sie suchen, aber es ist in der Nähe.

Wie über dieses

public static class MethodInfoExtension 
     { 
      public static string MethodSignature(this MethodInfo mi) 
      { 
       String[] param = mi.GetParameters() 
           .Select(p => String.Format("{0} {1}",p.ParameterType.Name,p.Name)) 
           .ToArray(); 


      string signature = String.Format("{0} {1}({2})", mi.ReturnType.Name, mi.Name, String.Join(",", param)); 

      return signature; 
     } 
    } 

    var methods = typeof(string).GetMethods().Where(x => x.Name.Equals("Compare")); 

    foreach(MethodInfo item in methods) 
    { 
     Console.WriteLine(item.MethodSignature()); 
    } 

Dies ist das Ergebnis

Int32 vergleichen (String strA, Int32 indexA, String strB, Int32 indexB, Int32 Länge, StringComparison comparisonType)

+0

Danke. Leider erfordert mein Anwendungsfall die Parameternamen für die Methode, die MethodInfo.ToString() nicht ausgibt. – LBushkin

+1

Ja, es zeigt auch keine Methodenattribute an. –

0

Überprüfen Sie die Methode GetParameters() auf MethodBase. Dadurch erhalten Sie Informationen über die Parameter einschließlich des Namens des Parameters. Ich glaube nicht, dass eine bereits existierende Methode existiert, um den Namen auszudrucken, aber die ParameterInfo [] zu verwenden, um das aufzubauen, sollte trivial sein.

Wie wäre es damit:

public string GetSignature(MethodInfo mi) 
{ 
    if(mi == null) 
    return ""; 
    StringBuilder sb = new StringBuilder(); 

    if(mi.IsPrivate) 
    sb.Append("private "); 
    else if(mi.IsPublic) 
    sb.Append("public "); 
    if(mi.IsAbstract) 
    sb.Append("abstract "); 
    if(mi.IsStatic) 
    sb.Append("static "); 
    if(mi.IsVirtual) 
    sb.Append("virtual "); 

    sb.Append(mi.ReturnType.Name + " "); 

    sb.Append(mi.Name + "("); 

    String[] param = mi.GetParameters() 
    .Select(p => String.Format(
       "{0} {1}",p.ParameterType.Name,p.Name)) 
          .ToArray(); 


    sb.Append(String.Join(", ",param)); 

    sb.Append(")"); 

    return sb.ToString(); 
} 
24
using System.Text; 

namespace System.Reflection 
{ 
    public static class MethodInfoExtensions 
    { 
     /// <summary> 
     /// Return the method signature as a string. 
     /// </summary> 
     /// <param name="method">The Method</param> 
     /// <param name="callable">Return as an callable string(public void a(string b) would return a(b))</param> 
     /// <returns>Method signature</returns> 
     public static string GetSignature(this MethodInfo method, bool callable = false) 
     { 
      var firstParam = true; 
      var sigBuilder = new StringBuilder(); 
      if (callable == false) 
      { 
       if (method.IsPublic) 
        sigBuilder.Append("public "); 
       else if (method.IsPrivate) 
        sigBuilder.Append("private "); 
       else if (method.IsAssembly) 
        sigBuilder.Append("internal "); 
       if (method.IsFamily) 
        sigBuilder.Append("protected "); 
       if (method.IsStatic) 
        sigBuilder.Append("static "); 
       sigBuilder.Append(TypeName(method.ReturnType)); 
       sigBuilder.Append(' '); 
      } 
      sigBuilder.Append(method.Name); 

      // Add method generics 
      if(method.IsGenericMethod) 
      { 
       sigBuilder.Append("<"); 
       foreach(var g in method.GetGenericArguments()) 
       { 
        if (firstParam) 
         firstParam = false; 
        else 
         sigBuilder.Append(", "); 
        sigBuilder.Append(TypeName(g)); 
       } 
       sigBuilder.Append(">"); 
      } 
      sigBuilder.Append("("); 
      firstParam = true; 
      var secondParam = false; 
      foreach (var param in method.GetParameters()) 
      { 
       if (firstParam) 
       { 
        firstParam = false; 
        if (method.IsDefined(typeof(System.Runtime.CompilerServices.ExtensionAttribute), false)) 
        { 
         if (callable) 
         { 
          secondParam = true; 
          continue; 
         } 
         sigBuilder.Append("this "); 
        } 
       } 
       else if (secondParam == true) 
        secondParam = false; 
       else 
        sigBuilder.Append(", "); 
       if (param.ParameterType.IsByRef) 
        sigBuilder.Append("ref "); 
       else if (param.IsOut) 
        sigBuilder.Append("out "); 
       if (!callable) 
       { 
        sigBuilder.Append(TypeName(param.ParameterType)); 
        sigBuilder.Append(' '); 
       } 
       sigBuilder.Append(param.Name); 
      } 
      sigBuilder.Append(")"); 
      return sigBuilder.ToString(); 
     } 

     /// <summary> 
     /// Get full type name with full namespace names 
     /// </summary> 
     /// <param name="type">Type. May be generic or nullable</param> 
     /// <returns>Full type name, fully qualified namespaces</returns> 
     public static string TypeName(Type type) 
     { 
      var nullableType = Nullable.GetUnderlyingType(type); 
      if (nullableType != null) 
       return nullableType.Name + "?"; 

      if (!(type.IsGenericType && type.Name.Contains('`'))) 
       switch (type.Name) 
       { 
        case "String": return "string"; 
        case "Int32": return "int"; 
        case "Decimal": return "decimal"; 
        case "Object": return "object"; 
        case "Void": return "void"; 
        default: 
         { 
          return string.IsNullOrWhiteSpace(type.FullName) ? type.Name : type.FullName; 
         } 
       } 

      var sb = new StringBuilder(type.Name.Substring(0, 
      type.Name.IndexOf('`')) 
      ); 
      sb.Append('<'); 
      var first = true; 
      foreach (var t in type.GetGenericArguments()) 
      { 
       if (!first) 
        sb.Append(','); 
       sb.Append(TypeName(t)); 
       first = false; 
      } 
      sb.Append('>'); 
      return sb.ToString(); 
     } 

    } 
} 

Diese Griffe praktisch alles, einschließlich Erweiterungsmethoden. Habe einen Vorsprung von http://www.pcreview.co.uk/forums/getting-correct-method-signature-t3660896.html.

I verwendet es in tandum mit einer T4-Vorlage Überlastungen für alle Queryable und Enumerable Linq Erweiterungsmethoden zu erzeugen.

+10

Danke dafür ... hat mir viel Zeit erspart. Ich habe es etwas weiter entwickelt, um Param-Arrays, optionale Parameter und generische Constraints sowie Eigenschaften zu handhaben. Immer noch nicht 100% komplett, aber ich dachte, ich würde es weitergeben. https://gist.github.com/4476307 –

+1

@jamietre Nizza, habe ich gegabelt, ich muss damit herumspielen. –

+1

Danke, das funktioniert auch für Generik-Methoden und generische Parameter –

Verwandte Themen