Getting correct method signature

A

Andrus

How to get syntactically correct signature which compiles for code template
grneration ?
I tried code below but it creates syntactically incorrect signature.

Andrus.

using System;
using System.Collections.Generic;

public class MainClass
{
static string GetSignature(Type xTheType, string method)
{
var xModule = xTheType.Module;
var xTheMethod = xTheType.GetMethod(method);
return xTheMethod.ToString();
}

public static void Main()
{
// Observed: Void Test(System.Object,
System.Collections.Generic.List`1[System.String])
// Expected: public void Test(object p1, List<string> p2)
// or some other syntactically correct signature
Console.WriteLine(GetSignature(typeof(MainClass), "Test"));
}

public void Test(object p1, List<string> p2)
{
}
}
 
J

Jeff Johnson

// Observed: Void Test(System.Object,
System.Collections.Generic.List`1[System.String])

The `x in the type name tells you how many parameters the generic takes, and
the parameters (if that's the right word) are then listed afterwords in
brackets, comma delimited, I believe. (Check it on a Dictionary.) So you'd
just need to do a little parsing and substringing to rewrite the type in a
C#-friendly manner.
 
A

Andrus

Jeff,
// Observed: Void Test(System.Object,
System.Collections.Generic.List`1[System.String])

The `x in the type name tells you how many parameters the generic takes,
and the parameters (if that's the right word) are then listed afterwords
in brackets, comma delimited, I believe. (Check it on a Dictionary.) So
you'd just need to do a little parsing and substringing to rewrite the
type in a C#-friendly manner.

Thank you.
Where to find some sample code for this?
How to get method parameter names also as defined in method code?
Why it outputs Void with upper case ?

andrus.
 
J

Jeff Johnson

// Observed: Void Test(System.Object,
System.Collections.Generic.List`1[System.String])

The `x in the type name tells you how many parameters the generic takes,
and the parameters (if that's the right word) are then listed afterwords
in brackets, comma delimited, I believe. (Check it on a Dictionary.) So
you'd just need to do a little parsing and substringing to rewrite the
type in a C#-friendly manner.
Where to find some sample code for this?

Sample code for what? Manipulating strings? I'm sure you can do something
that simple....
How to get method parameter names also as defined in method code?

Hmm, I don't deal with this kind of Reflection very often. Let me take a
look.

Okay, from a cursory glance at MSDN, calling MethodInfo.GetParameters() gets
you an array of ParameterInfo objects. These objects have a Name property.
Does that work for you?
Why it outputs Void with upper case ?

I'm willing to bet that that's the Frameworks "neutral" version of the
keyword, just like you're getting a type of System.Object instead of the
C#-specific "object" keyword.

I just noticed you're using the "var" keyword. I don't use the 3.x Framework
(I'm basing my responses on 2.0) so I don't know if anything's changed. I
doubt it, since my MSDN is current.
 
J

Jeff Johnson

Sample code for C# method signature disassembler.

Well, you're kind of in luck today. I dabbled in writing my own object
browser a while back, and I still have the code. It's in VB, and this was
pre-generics, so you're not going to get exactly what you want (note the
TODO near the end) but it should be a start.

Private Function GetSignature(ByVal method As MethodInfo) As String
Dim firstParam As Boolean = True
' TODO: Don't hardcode the function open/close characters
Dim sigBuilder As StringBuilder = New StringBuilder(method.Name & "(")
Dim displayType As String

For Each param As ParameterInfo In method.GetParameters()
If param.ParameterType.FullName IsNot Nothing Then
Dim paramType As String = param.ParameterType.FullName

If paramType.EndsWith("&") Then
paramType = paramType.Substring(0, paramType.Length - 1)
End If

Select Case paramType.ToLower()
Case "system.object"
If m_viewStyle = ViewStyle.CSharp Then
displayType = "object"
Else
displayType = "Object"
End If
Case "system.string"
If m_viewStyle = ViewStyle.CSharp Then
displayType = "string"
Else
displayType = "String"
End If
Case "system.int32"
If m_viewStyle = ViewStyle.CSharp Then
displayType = "int"
Else
displayType = "Integer"
End If
Case "system.int16"
If m_viewStyle = ViewStyle.CSharp Then
displayType = "short"
Else
displayType = "Short"
End If
Case "system.byte"
If m_viewStyle = ViewStyle.CSharp Then
displayType = "byte"
Else
displayType = "Byte"
End If
Case "system.int64"
If m_viewStyle = ViewStyle.CSharp Then
displayType = "long"
Else
displayType = "Long"
End If
Case "system.boolean"
If m_viewStyle = ViewStyle.CSharp Then
displayType = "bool"
Else
displayType = "Boolean"
End If
Case "system.char"
If m_viewStyle = ViewStyle.CSharp Then
displayType = "char"
Else
displayType = "Char"
End If
Case "system.datetime"
If m_viewStyle = ViewStyle.CSharp Then
displayType = paramType ' No equivalent in C#
Else
displayType = "Date"
End If
Case "system.double"
If m_viewStyle = ViewStyle.CSharp Then
displayType = "double"
Else
displayType = "Double"
End If
Case "system.single"
If m_viewStyle = ViewStyle.CSharp Then
displayType = "float"
Else
displayType = "Single"
End If
Case "system.sbyte"
If m_viewStyle = ViewStyle.CSharp Then
displayType = "sbyte"
Else
displayType = "SByte"
End If
Case "system.uint32"
If m_viewStyle = ViewStyle.CSharp Then
displayType = "uint"
Else
displayType = "UInteger"
End If
Case "system.uint16"
If m_viewStyle = ViewStyle.CSharp Then
displayType = "ushort"
Else
displayType = "UShort"
End If
Case "system.uint64"
If m_viewStyle = ViewStyle.CSharp Then
displayType = "ulong"
Else
displayType = "ULong"
End If
Case "system.decimal"
If m_viewStyle = ViewStyle.CSharp Then
displayType = "decimal"
Else
displayType = paramType ' No equivalent in VB
End If
Case Else
displayType = paramType
End Select

If firstParam Then
firstParam = False
Else
sigBuilder.Append(", ")
End If

If m_viewStyle = ViewStyle.CSharp Then
If param.ParameterType.IsByRef Then
sigBuilder.Append("ref ")
ElseIf param.IsOut Then
sigBuilder.Append("out ")
End If
Else
If param.ParameterType.IsByRef Then
sigBuilder.Append("ByRef ")
End If
End If

sigBuilder.Append(displayType)
Else
' TODO: Handle generics
Return String.Empty
End If
Next

sigBuilder.Append(")")

Return sigBuilder.ToString()
End Function
 
A

Andrus

Well, you're kind of in luck today. I dabbled in writing my own object
browser a while back, and I still have the code. It's in VB, and this was
pre-generics, so you're not going to get exactly what you want (note the
TODO near the end) but it should be a start.

Thank you. Using this I created code below.
If I pass method name containing generic type parameters to GetMSignature
GetMethod returns null.

How to change this that it works for generic method also: builds signature
with generic type parameters and their constraints ?

Andrus.


static string GetMSignature(Type xTheType, string method)
{
var xModule = xTheType.Module;
MethodInfo xTheMethod = xTheType.GetMethod(method);
xTheMethod = xTheType.GetMethod(method);
return GetSignature(xTheMethod);
}


static string GetSignature(MethodInfo method)
{
bool firstParam = true;
StringBuilder sigBuilder = new
StringBuilder(ReflectionUtil.TypeName(method.ReturnType));
sigBuilder.Append(' ');
sigBuilder.Append(method.Name + "(");
foreach (ParameterInfo param in method.GetParameters())
{
if (firstParam)
firstParam = false;
else
sigBuilder.Append(", ");

if (param.ParameterType.IsByRef)
sigBuilder.Append("ref ");
else if (param.IsOut)
sigBuilder.Append("out ");
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)
{
Type nullableType = Nullable.GetUnderlyingType(type);
if (nullableType != null)
return nullableType.Name + "?";

if (!type.IsGenericType)
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 type.FullName;
}

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

Jeff Johnson

Thank you. Using this I created code below.
If I pass method name containing generic type parameters to GetMSignature
GetMethod returns null.

How to change this that it works for generic method also: builds signature
with generic type parameters and their constraints ?

I'm afraid that's up to you. The MethodInfo class has methods and properties
like GetGenericArguments() and IsGeneric method. As you can see, I never
implemented them, nor did I even look into them.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top