Print full signature of a method from a MethodInfo

Unfortunately I don't believe there is a built in method that would do that. Your best be would be to create your own signature by investigating the MethodInfo class

EDIT: I just did this

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

and you get

Void Main(System.String[])

This might not be what you're looking for, but it's close.

How about this

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());
}

This is the result

Int32 Compare(String strA,Int32 indexA,String strB,Int32 indexB,Int32 length,StringComparison comparisonType)


Checkout the GetParameters() method on MethodBase. That will give you the info about the parameters including the name of the parameter. I don't believe a pre-existing method exists to print out the name but using the ParameterInfo[] to build that should be trivial.

How about this:

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();
}

Update 3/22/2018

I've rewritten the code, added a few tests, and uploaded it to GitHub

It's also available through nuget

Eltons.ReflectionKit NuGet

Answer

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();
        }

    }
}

This handles practically everything, including extension methods. Got a head start from http://www.pcreview.co.uk/forums/getting-correct-method-signature-t3660896.html.

I used it in tandum with a T4 template to generate overloads for all the Queryable and Enumerable Linq extension methods.