How can I parse C#-style generic type names of the format List<int>
or Dictionary<string,int>
or even more complex Dictionary<string,Dictionary<System.String,int[]>>
. Assume that these names are strings and may not actually represent existing types. It should just as easily be be able to parse BogusClass<A,B,Vector<C>>
. To be clear, I am NOT interested in parsing .NET internal type names of the format List`1[[System.Int32]]
, but actual C# type names as they would appear in the source code, with or without namespace qualifiers using dot notation.
Regular expressions are out because these are nested structures. I thought perhaps the System.CodeDom.CodeTypeReference constructor would parse it for me since it has string BaseType
and CodeTypeReferenceCollection TypeArguments
members, but those apparently need to be set manually.
CodeTypeReference is the kind of structure I need:
class TypeNameStructure
{
public string Name;
public TypeNameStructure[] GenericTypeArguments;
public bool IsGenericType{get;}
public bool IsArray{get;} //would be nice to detect this as well
public TypeNameStructure( string friendlyCSharpName )
{
//Parse friendlyCSharpName into name and generic type arguments recursively
}
}
Are there any existing classes in the framework to achieve this kind of type name parsing? If not, how would I go about parsing this?
Well, I had a lot of fun writing this little parsing class using
Regex
and named capture groups(?<Name>group)
.My approach was that each 'type definition' string could be broken up as a set of the following: Type Name, optional Generic Type, and optional array marker '[ ]'.
So given the classic
Dictionary<string, byte[]>
you would haveDictionary
as the type name andstring, byte[]
as your inner generic type string.We can split the inner generic type on the comma (',') character and recursively parse each type string using the same
Regex
. Each successful parse should be added to the parent type information and you can build a tree hierarchy.With the previous example, we would end up with an array of
{string, byte[]}
to parse. Both of these are easily parsed and set to part ofDictionary
's inner types.On
ToString()
it's simply a matter of recursively outputting each type's friendly name, including inner types. SoDictionary
would output his type name, and iterate through all inner types, outputting their type names and so forth.I made a console app to test it, it seems to work with most cases I threw at it.
Here's the code:
And here's the output:
There are some possible lingering issues, such as multidimensional arrays. It will more than likely fail on something like
int[,]
orstring[][]
.Answering own question. I wrote the following class achieve the results I need; give it a spin.
If I run the following:
It correctly produces the following output, representing the TypeName as a string: