TypeNameFormatter is a small .NET library for formatting type names à la C#.
Have you ever stumbled over the cryptic formatting of Type objects?
var someType = typeof(IEnumerable<int[]>);
Console.WriteLine(someType);
// => System.Collections.Generic.IEnumerable`1[System.Int32[]]If you'd rather see something that looks more like a C# type name, then this library might be for you:
using TypeNameFormatter;
var someType = typeof(IEnumerable<int[]>);
Console.WriteLine(someType.GetFormattedName());
// => IEnumerable<int[]>Formatting any Type involves more special cases than you might expect (such as generic types, nested types, multi-dimensional and jagged arrays, by-reference and pointer types). This library deals with all of those, so that you don't have to.
By importing the TypeNameFormatter namespace, the following extension methods become available:
- 
stringBuilder.AppendFormattedName(Type type, [TypeNameFormatOptions options]):
 Appends a C#-formatted type name to the givenStringBuilder.
- 
type.GetFormattedName([TypeNameFormatOptions options]):
 Returns a C#-formatted type name as a string. (This is a convenience method that does exactly the same as the above, using a throw-awayStringBuilder.)
Both methods allow you to specify any combination of the following TypeNameFormatOptions flags:
- 
Namespaces:
 Namespaces should be included. (For example,System.Actioninstead ofAction.)
- 
NoAnonymousTypes: Anonymous types should not have their "display class" name transformed to a more legible syntax. (For example,<>f__AnonymousType5<string, int>instead of{string Name, int Count}.)
- 
NoGenericParameterNames:
 Parameter names of an open generic type should be omitted. (For example,IEnumerable<>instead ofIEnumerable<T>. Note that this setting does not affect closed generic types; their arguments are always included.)
- 
NoKeywords:
 Primitive types should not be mapped to their corresponding C# language keywords. (For example,Int32instead ofint.)
- 
NoNullableQuestionMark: Nullable types should not be formatted using C# question mark syntax. (For example,Nullable<int>instead ofint?.)
- 
NoTuple: Value tuple types should not be formatted using C# tuple syntax. (For example,ValueTuple<bool, int>instead of(bool, int).)
If you think you've found a bug, please raise an issue so it can be looked into. (Make sure to mention the type that doesn't get formatted as expected.)
- 
If you're targeting the .NET Framework, you can use good old System.CodeDom(which isn't particularly fast, however):using Microsoft.CSharp; using System.CodeDom; static string GetFormattedName(this Type type) { using (var provider = new CSharpCodeProvider()) { var typeReference = new CodeTypeReference(type); return provider.GetTypeOutput(typeReference); } } 
- 
You could perhaps use Microsoft's .NET Compiler Platform (Roslyn), but that is a large library that can do much more than is needed. 
The TypeNameFormatter.Sources NuGet package comes with a few MSBuild properties that you can set inside your project file (inside a <PropertyGroup>):
- 
<TypeNameFormatterInternal>:
 This property determines the visibility of the types provided by TypeNameFormatter:- If set to True(the default), they are declaredinternal.
- If set to False, they are declaredpublic.
 
- If set to 
- 
<TypeNameFormatterProjectNodeName>:
 This property determines the name under which TypeNameFormatter's single.csfile will appear in e.g. Visual Studio's Solution Explorer:- If set to TypeNameFormatter.cs(the default), a hidden linked file by that name will be added to your project's root.
- If set to any other relative file path, a visible linked file will be added to your project.
 
- If set to 
For example:
<Project …>
  …
  <PropertyGroup>
    <!-- Make TypeNameFormatter's types `public` instead of `internal`: -->
    <TypeNameFormatterInternal>False<TypeNameFormatterInternal>
    <!-- Make a linked file `TypeNameFormatter.cs` show up in Solution Explorer
         under a folder node named `Utilities`: -->
    <TypeNameFormatterProjectNodeName>Utilities\TypeNameFormatter.cs</TypeNameFormatterProjectNodeName>
  </PropertyGroup>
  …
</Project>