22
33public static class TypeExtensions
44{
5- private static readonly Dictionary < Type , string > _csharpAliases = new ( )
6- {
7- { typeof ( void ) , "void" } ,
8- { typeof ( bool ) , "bool" } ,
9- { typeof ( byte ) , "byte" } ,
10- { typeof ( sbyte ) , "sbyte" } ,
11- { typeof ( char ) , "char" } ,
12- { typeof ( decimal ) , "decimal" } ,
13- { typeof ( double ) , "double" } ,
14- { typeof ( float ) , "float" } ,
15- { typeof ( int ) , "int" } ,
16- { typeof ( uint ) , "uint" } ,
17- { typeof ( long ) , "long" } ,
18- { typeof ( ulong ) , "ulong" } ,
19- { typeof ( object ) , "object" } ,
20- { typeof ( short ) , "short" } ,
21- { typeof ( ushort ) , "ushort" } ,
22- { typeof ( string ) , "string" }
23- } ;
5+ private const string Prefix = "CSharp:" ;
246
7+ /// <summary>
8+ /// Returns the canonical AI type name with prefix "CSharp:", avoiding nested prefixes.
9+ /// </summary>
2510 public static string GetCanonicalAiTypeName ( Type type )
2611 {
27- if ( type == null )
28- throw new ArgumentNullException ( nameof ( type ) ) ;
12+ if ( type == null ) throw new ArgumentNullException ( nameof ( type ) ) ;
13+ return Prefix + GetCanonicalInternal ( type ) ;
14+ }
2915
16+ private static string GetCanonicalInternal ( Type type )
17+ {
3018 // Nullable<T> → T?
31- var underlyingNullable = Nullable . GetUnderlyingType ( type ) ;
32- if ( underlyingNullable != null )
33- return $ "CSharp:{ GetCanonicalAiTypeName ( underlyingNullable ) } ?";
19+ if ( Nullable . GetUnderlyingType ( type ) is Type underlyingNullable )
20+ return $ "{ GetCanonicalInternal ( underlyingNullable ) } ?";
3421
3522 // Arrays
3623 if ( type . IsArray )
3724 {
38- var elem = GetCanonicalAiTypeName ( type . GetElementType ( ) ! ) ;
39- return $ "CSharp:{ elem } { new string ( '[' , type . GetArrayRank ( ) ) } { new string ( ']' , type . GetArrayRank ( ) ) } ";
25+ string elem = GetCanonicalInternal ( type . GetElementType ( ) ! ) ;
26+ // C#-style multi-dim array: [,,]
27+ string commas = new string ( ',' , type . GetArrayRank ( ) - 1 ) ;
28+ //string brackets = new string('[', type.GetArrayRank()) + new string(']', type.GetArrayRank());
29+ return $ "{ elem } [{ commas } ]";
4030 }
4131
4232 // Generic types
4333 if ( type . IsGenericType )
4434 {
45- string typeName = type . GetGenericTypeDefinition ( ) . FullName ! ;
46- int backtick = typeName . IndexOf ( '`' ) ;
47- if ( backtick > 0 )
48- typeName = typeName [ ..backtick ] ;
35+ string fullName = type . GetGenericTypeDefinition ( ) . FullName ! ;
36+ int idx = fullName . IndexOf ( '`' ) ;
37+ if ( idx > 0 )
38+ fullName = fullName [ ..idx ] ;
4939
5040 var args = type . GetGenericArguments ( )
51- . Select ( GetCanonicalAiTypeName ) ;
41+ . Select ( GetCanonicalInternal ) ;
5242
53- return $ "CSharp:{ typeName } [{ string . Join ( ", " , args ) } ]";
54- }
55-
56- // Non-generic, non-nullable, non-array
57- return $ "CSharp:{ type . FullName } ";
58- }
59-
60- public static string GetFriendlyTypeName ( Type type )
61- {
62- if ( type == null )
63- throw new ArgumentNullException ( nameof ( type ) ) ;
64-
65- // Handle arrays
66- if ( type . IsArray )
67- {
68- return $ "{ GetFriendlyTypeName ( type . GetElementType ( ) ! ) } [{ new string ( ',' , type . GetArrayRank ( ) - 1 ) } ]";
43+ return $ "{ fullName } [{ string . Join ( ", " , args ) } ]";
6944 }
7045
71- // Handle nullable types
72- var underlyingNullable = Nullable . GetUnderlyingType ( type ) ;
73- if ( underlyingNullable != null )
74- {
75- return $ "{ GetFriendlyTypeName ( underlyingNullable ) } ?";
76- }
77-
78- // Handle generic types
79- if ( type . IsGenericType )
80- {
81- var typeDef = type . GetGenericTypeDefinition ( ) ;
82- var genericArgs = type . GetGenericArguments ( ) . Select ( GetFriendlyTypeName ) . ToArray ( ) ;
83-
84- var typeName = type . Name ;
85- var backtickIndex = typeName . IndexOf ( '`' ) ;
86- if ( backtickIndex > 0 )
87- typeName = typeName . Substring ( 0 , backtickIndex ) ;
88-
89- return $ "{ typeName } <{ string . Join ( ", " , genericArgs ) } >";
90- }
91-
92- // Map to C# alias if possible
93- if ( _csharpAliases . TryGetValue ( type , out var alias ) )
94- return alias ;
95-
96- return type . Name ; // fallback to CLR type name
46+ // Simple type
47+ return type . FullName ! ;
9748 }
9849}
0 commit comments