8
votes

Voice correcte d'obtenir le nom de base d'un type générique dans .NET est via la sous-chaîne?

Si j'ai ceci: xxx pré>

Comment obtenir "system.collections.generic.dictionary" code> comme une chaîne? Est le meilleur moyen / unique de faire ceci: p> xxx pré>

semble un peu piraté de moi cependant. P>

La raison pour laquelle je veux que ce soit que je veux prendre A code> type code> objet et produire du code similaire à celui que l'on a trouvé dans un fichier de code source C #. Je produit des modèles de texte et je dois ajouter des types comme des chaînes dans la source et que la propriété FullName Code> produit quelque chose comme ceci: P>

/// <summary>
/// This method takes a type and produces a proper full type name for it, expanding generics properly.
/// </summary>
/// <param name="type">
/// The type to produce the full type name for.
/// </param>
/// <returns>
/// The type name for <paramref name="type"/> as a string.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <para><paramref name="type"/> is <c>null</c>.</para>
/// </exception>
public static String TypeToString(Type type)
{
    #region Parameter Validation

    if (Object.ReferenceEquals(null, type))
        throw new ArgumentNullException("type");

    #endregion

    if (type.IsGenericType)
    {
        if (type.GetGenericTypeDefinition() == typeof(Nullable<>))
        {
            Type underlyingType = type.GetGenericArguments()[0];
            return String.Format("{0}?", TypeToString(underlyingType));
        }
        String baseName = type.FullName.Substring(0, type.FullName.IndexOf("`"));
        return baseName + "<" + String.Join(", ", (from paramType in type.GetGenericArguments()
                                                   select TypeToString(paramType)).ToArray()) + ">";
    }
    else
    {
        return type.FullName;
    }
}


0 commentaires

4 Réponses :


2
votes

AFAIK La notation interne pour les génériques utilise la notation `x pour indiquer le nombre de paramètres de type au type générique. C'est à dire. 2 indique que le dictionnaire a besoin de deux types pour la fermer. C'est la même notation utilisée par l'ildasme et la réflexion.


2 commentaires

Correct, mais est le seul moyen d'obtenir la partie du nom avant la partie générique à l'aide de la sous-chaîne, comme je l'ai montré, ou y a-t-il une réflexion de Néater, une propriété ou une méthode que je ne connais pas?


Alors que Johannesh souligne sa réponse, ce que vous voyez est la notation de l'IL. Si vous voulez quelque chose d'autre (comme C #), vous devez la cartographier vous-même. Nous avons quelques outils internes qui font quelque chose de similaire à ce que vous suggérez. Je ne suis au courant d'aucune autre manière d'obtenir la syntaxe C #, mais, d'autre part, je supposerais que le format soit corrigé et que vous devriez ainsi être capable de le transformer en toute sécurité vous-même.



7
votes

Le problème est que vous voulez une notation spécifique linguistique, dans ce cas c #. xxx

peut-être que vous pouvez appeler un service de langue pour obtenir la chaîne souhaitée, mais vous êtes probablement mieux mieux de générer la chaîne vous-même.


3 commentaires

La documentation MSDN utilise la syntaxe C # (sauf pour le titre): MSDN.MicRosoft. com / fr-nous / bibliothèque / xfhwa508.aspx


@Chris, vous pouvez choisir quelle représentation utilise MSDN ne doit pas nécessairement être c #.


Pour le script, c'est - la hiérarchie et les méthodes / propriétés de l'objet



6
votes

Vous pouvez utiliser CODEDOM pour générer une déclaration C # plus "normale". XXX PRE>

Le code ci-dessus a la sortie suivante: p>

System.Collections.Generic.Dictionary<string, int>    


0 commentaires

3
votes

est-ce plus proche de ce que vous recherchez?

Il utilise CodeTypeReferenceExpression code> et ne nécessite aucun autre SUBSTRING code> ou remplacer code> Appels: p>

var type = typeof(Dictionary<string, string>);
Console.WriteLine(TypeToString(type));

// ...

public static string TypeToString(Type type)
{
    if (type == null) throw new ArgumentNullException("type");

    var sb = new StringBuilder();
    using (var sw = new StringWriter(sb))
    {
        var expr = new CodeTypeReferenceExpression(type);

        var prov = new CSharpCodeProvider();
        prov.GenerateCodeFromExpression(expr, sw, new CodeGeneratorOptions());
    }
    return sb.ToString();
}


1 commentaires

@John: Vous avez raison, mais cela ne signifie pas que cette réponse est fausse et / ou mérite un bowvote. En outre, la question demande comment faire cela sans manipulation de chaîne supplémentaire et la réponse de BobbymCr nécessite toujours un appel .