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.Action
instead 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,Int32
instead 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.cs
file 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>