Obtenez le nom du type

Comment puis-je obtenir le nom complet complet du type générique?

Par exemple: Ce code

typeof(List).Name 

revenir

Liste`1

au lieu de

 List 

Comment obtenir un bon nom?

 typeof(List).ToSsortingng() 

retourne System.Collections.Generic.List`1 [System.Ssortingng] mais je veux obtenir le nom initial:

 List 

Est-ce que c’est réel?

Utilisez la propriété FullName .

 typeof(List).FullName 

Cela vous donnera les parameters namespace + class + type.

Ce que vous demandez, c’est une syntaxe spécifique à C #. En ce qui concerne .NET, cela convient:

 System.Collections.Generic.List`1[System.Ssortingng] 

Donc, pour obtenir ce que vous voulez, il vous faudrait écrire une fonction pour la construire comme vous le souhaitez. Peut-être comme ça:

 static ssortingng GetCSharpRepresentation( Type t, bool sortingmArgCount ) { if( t.IsGenericType ) { var genericArgs = t.GetGenericArguments().ToList(); return GetCSharpRepresentation( t, sortingmArgCount, genericArgs ); } return t.Name; } static ssortingng GetCSharpRepresentation( Type t, bool sortingmArgCount, List availableArguments ) { if( t.IsGenericType ) { ssortingng value = t.Name; if( sortingmArgCount && value.IndexOf("`") > -1 ) { value = value.Subssortingng( 0, value.IndexOf( "`" ) ); } if( t.DeclaringType != null ) { // This is a nested type, build the nesting type first value = GetCSharpRepresentation( t.DeclaringType, sortingmArgCount, availableArguments ) + "+" + value; } // Build the type arguments (if any) ssortingng argSsortingng = ""; var thisTypeArgs = t.GetGenericArguments(); for( int i = 0; i < thisTypeArgs.Length && availableArguments.Count > 0; i++ ) { if( i != 0 ) argSsortingng += ", "; argSsortingng += GetCSharpRepresentation( availableArguments[0], sortingmArgCount ); availableArguments.RemoveAt( 0 ); } // If there are type arguments, add them with < > if( argSsortingng.Length > 0 ) { value += "<" + argString + ">"; } return value; } return t.Name; } 

Pour ces types (avec true en tant que 2nd param):

 typeof( List ) ) typeof( List> ) 

Il retourne:

 List List> 

En général cependant, je parie que vous n’avez probablement pas besoin de la représentation C # de votre code et peut-être que si vous le faites, un format meilleur que la syntaxe C # serait plus approprié.

Vous pouvez utiliser ceci:

 public static ssortingng GetTypeName(Type t) { if (!t.IsGenericType) return t.Name; if (t.IsNested && t.DeclaringType.IsGenericType) throw new NotImplementedException(); ssortingng txt = t.Name.Subssortingng(0, t.Name.IndexOf('`')) + "<"; int cnt = 0; foreach (Type arg in t.GetGenericArguments()) { if (cnt > 0) txt += ", "; txt += GetTypeName(arg); cnt++; } return txt + ">"; } 

Par exemple:

 static void Main(ssortingng[] args) { var obj = new Dictionary, int>>(); ssortingng s = GetTypeName(obj.GetType()); Console.WriteLine(s); Console.ReadLine(); } 

Sortie:

 Dictionary, Int32>> 
 typeof(List).ToSsortingng() 

Si vous avez une instance de la liste, vous pouvez appeler .ToSsortingng () et obtenir ce qui suit.

 System.Collections.Generic.List`1[System.Ssortingng] 

Cela s’ajoute aux méthodes fournies par les autres réponses directement contre le type plutôt que sur l’instance.

Edit: Lors de votre édition, je ne pense pas que ce soit possible sans fournir votre propre méthode d’parsing, car List est un raccourci C # pour la manière dont le type est implémenté, un peu comme si vous typeof(int).ToSsortingng() , ce qui est capturé n’est pas “int” mais le nom CTS, System.Int32 .

Voici ma mise en œuvre, qui a bénéficié de la réponse de @ Hans ci-dessus et de la réponse de @ Jack sur une question dupliquée .

 public static ssortingng GetCSharpName( this Type type ) { ssortingng result; if ( primitiveTypes.TryGetValue( type, out result ) ) return result; else result = type.Name.Replace( '+', '.' ); if ( !type.IsGenericType ) return result; else if ( type.IsNested && type.DeclaringType.IsGenericType ) throw new NotImplementedException(); result = result.Subssortingng( 0, result.IndexOf( "`" ) ); return result + "<" + string.Join( ", ", type.GetGenericArguments().Select( GetCSharpName ) ) + ">"; } static Dictionary primitiveTypes = new Dictionary { { typeof(bool), "bool" }, { typeof(byte), "byte" }, { typeof(char), "char" }, { typeof(decimal), "decimal" }, { typeof(double), "double" }, { typeof(float), "float" }, { typeof(int), "int" }, { typeof(long), "long" }, { typeof(sbyte), "sbyte" }, { typeof(short), "short" }, { typeof(ssortingng), "ssortingng" }, { typeof(uint), "uint" }, { typeof(ulong), "ulong" }, { typeof(ushort), "ushort" }, }; 

Une amélioration de la réponse d’Adam Sills qui fonctionne avec des types nesteds non génériques et des définitions de type génériques:

 public class TypeNameSsortingngExtensions { public static ssortingng GetCSharpRepresentation(Type t) { return GetCSharpRepresentation(t, new Queue(t.GetGenericArguments())); } static ssortingng GetCSharpRepresentation(Type t, Queue availableArguments) { ssortingng value = t.Name; if (t.IsGenericParameter) { return value; } if (t.DeclaringType != null) { // This is a nested type, build the parent type first value = GetCSharpRepresentation(t.DeclaringType, availableArguments) + "+" + value; } if (t.IsGenericType) { value = value.Split('`')[0]; // Build the type arguments (if any) ssortingng argSsortingng = ""; var thisTypeArgs = t.GetGenericArguments(); for (int i = 0; i < thisTypeArgs.Length && availableArguments.Count > 0; i++) { if (i != 0) argSsortingng += ", "; argSsortingng += GetCSharpRepresentation(availableArguments.Dequeue()); } // If there are type arguments, add them with < > if (argSsortingng.Length > 0) { value += "<" + argString + ">"; } } return value; } [TestCase(typeof(List), "List")] [TestCase(typeof(List>), "List>")] [TestCase(typeof(Stupid.Stupider), "Stupid+Stupider")] [TestCase(typeof(Dictionary.KeyCollection), "Dictionary+KeyCollection")] [TestCase(typeof(Nullable), "Nullable")] [TestCase(typeof(Point?), "Nullable")] [TestCase(typeof(TypeNameSsortingngExtensions), "TypeNameSsortingngExtensions")] [TestCase(typeof(Another), "TypeNameSsortingngExtensions+Another")] [TestCase(typeof(G<>), "TypeNameStringExtensions+G")] [TestCase(typeof(G), "TypeNameSsortingngExtensions+G")] [TestCase(typeof(G), "TypeNameSsortingngExtensions+G")] [TestCase(typeof(H<,>), "TypeNameSsortingngExtensions+H")] [TestCase(typeof(H), "TypeNameSsortingngExtensions+H")] [TestCase(typeof(Another.I<>), "TypeNameStringExtensions+Another+I")] [TestCase(typeof(Another.I), "TypeNameSsortingngExtensions+Another+I")] [TestCase(typeof(G<>.Nested), "TypeNameStringExtensions+G+Nested")] [TestCase(typeof(G.Nested), "TypeNameSsortingngExtensions+G+Nested")] [TestCase(typeof(A<>.C<>), "TypeNameSsortingngExtensions+A+C")] [TestCase(typeof(A.C), "TypeNameSsortingngExtensions+A+C")] public void GetCSharpRepresentation_matches(Type type, ssortingng expected) { ssortingng actual = GetCSharpRepresentation(type); Assert.AreEqual(expected, actual); } public class G { public class Nested { } } public class A { public class C { } } public class H { } public class Another { public class I { } } } public class Stupid { public class Stupider { } } 

J’ai également choisi de renoncer à son sortingmArgCount , car je ne vois pas quand cela pourrait être utile, et d’utiliser un Queue car c’était l’intention (retirer les éléments au premier plan lorsqu’ils existent).

Une autre façon d’obtenir un nom de type sympa en utilisant une extension:

 typeof(Dictionary>>).CSharpName(); // output is: // Dictionary>> 

Le code d’extension:

 public static class TypeExtensions { public static ssortingng CSharpName(this Type type) { ssortingng typeName = type.Name; if (type.IsGenericType) { var genArgs = type.GetGenericArguments(); if (genArgs.Count() > 0) { typeName = typeName.Subssortingng(0, typeName.Length - 2); ssortingng args = ""; foreach (var argType in genArgs) { ssortingng argName = argType.Name; if (argType.IsGenericType) argName = argType.CSharpName(); args += argName + ", "; } typeName = ssortingng.Format("{0}<{1}>", typeName, args.Subssortingng(0, args.Length - 2)); } } return typeName; } } 

Si vous souhaitez utiliser le type générique de base:

 List lstSsortingng = new List(); Type type = lstSsortingng.GetType().GetGenericTypeDefinition(); 

En supposant que vous souhaitiez utiliser le type, faites quelque chose et vous n’avez pas vraiment besoin de la définition de chaîne qui n’est pas vraiment utile.

J’ai eu des problèmes avec les autres réponses dans certains cas, par exemple avec les tableaux, alors j’ai fini par en écrire un autre. Je n’utilise pas le texte de Type.Name ou similaire, sauf pour obtenir le nom complet des types, car je ne sais pas s’il est garanti que le format est identique dans les différentes versions .Net ou avec d’autres implémentations des bibliothèques. (Je suppose que ce n’est pas).

 ///  /// For the given type, returns its representation in C# code. ///  /// The type. /// Used internally, ignore. /// Used internally, ignore. /// The representation of the type in C# code. public static ssortingng GetTypeCSharpRepresentation(Type type, Stack genericArgs = null, SsortingngBuilder arrayBrackets = null) { SsortingngBuilder code = new SsortingngBuilder(); Type declaringType = type.DeclaringType; bool arrayBracketsWasNull = arrayBrackets == null; if (genericArgs == null) genericArgs = new Stack(type.GetGenericArguments()); int currentTypeGenericArgsCount = genericArgs.Count; if (declaringType != null) currentTypeGenericArgsCount -= declaringType.GetGenericArguments().Length; Type[] currentTypeGenericArgs = new Type[currentTypeGenericArgsCount]; for (int i = currentTypeGenericArgsCount - 1; i >= 0; i--) currentTypeGenericArgs[i] = genericArgs.Pop(); if (declaringType != null) code.Append(GetTypeCSharpRepresentation(declaringType, genericArgs)).Append('.'); if (type.IsArray) { if (arrayBrackets == null) arrayBrackets = new SsortingngBuilder(); arrayBrackets.Append('['); arrayBrackets.Append(',', type.GetArrayRank() - 1); arrayBrackets.Append(']'); Type elementType = type.GetElementType(); code.Insert(0, GetTypeCSharpRepresentation(elementType, arrayBrackets : arrayBrackets)); } else { code.Append(new ssortingng(type.Name.TakeWhile(c => char.IsLetterOrDigit(c) || c == '_').ToArray())); if (currentTypeGenericArgsCount > 0) { code.Append('<'); for (int i = 0; i < currentTypeGenericArgsCount; i++) { code.Append(GetTypeCSharpRepresentation(currentTypeGenericArgs[i])); if (i < currentTypeGenericArgsCount - 1) code.Append(','); } code.Append('>'); } if (declaringType == null && !ssortingng.IsNullOrEmpty(type.Namespace)) { code.Insert(0, '.').Insert(0, type.Namespace); } } if (arrayBracketsWasNull && arrayBrackets != null) code.Append(arrayBrackets.ToSsortingng()); return code.ToSsortingng(); } 

Je l’ai testé avec des types fous comme celui-ci et jusqu’à présent, il a parfaitement fonctionné:

 class C { public class D { public class E { public class K { public class P { public struct Q { } } } } } } type = typeof(List.EK[,][], Action[], double[][,]>, float>.P.Q>>[][,][,,,][][,,]); // Returns "System.Collections.Generic.List.EK[,][],System.Action[],System.Double[][,]>,System.Single>.P.Q>>[][,][,,,][][,,]": GetTypeCSharpRepresentation(type); 

Il y a peut-être encore des pièges auxquels je n’ai pas pensé, mais il y en a un connu: pour récupérer les noms, je ne reçois que les caractères qui répondent à la condition char.IsLetterOrDigit(c) || c == '_' char.IsLetterOrDigit(c) || c == '_' jusqu’à ce que l’un d’entre eux ne soit pas trouvé. Ainsi, tout nom de type utilisant des caractères autorisés ne répondant pas à la condition échouera.