在.NET中获取泛型类型的基本名称的正确方法是通过Substring?

ang*_*son 8 .net c# reflection types

如果我有这个:

Type t = typeof(Dictionary<String, String>);
Run Code Online (Sandbox Code Playgroud)

我怎么得到"System.Collections.Generic.Dictionary"一个字符串?这是最好/唯一的方法:

String n = t.FullName.Substring(0, t.FullName.IndexOf("`"));
Run Code Online (Sandbox Code Playgroud)

虽然看起来有点像哈希.

我想要这个的原因是我想要一个Type对象,并产生类似于C#源代码文件中的代码.我正在制作一些文本模板,我需要将类型作为字符串添加到源代码中,并且FullName属性产生如下内容:

System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=2.0.0.0,
Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=2.0.0.0,
Culture=neutral, PublicKeyToken=b77a5c561934e089]]
Run Code Online (Sandbox Code Playgroud)

而不是我想要的:

System.Collections.Generic.Dictionary<System.String, System.String>
Run Code Online (Sandbox Code Playgroud)

编辑:好的,这是最终的代码,对我来说似乎有点像黑客,但它有效:

/// <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;
    }
}
Run Code Online (Sandbox Code Playgroud)

Joh*_*esH 7

问题是您需要特定于语言的符号,在本例中为C#.

IL syntax:     [mscorlib]System.Collections.Generic.Dictionary`2<class [mscorlib]System.String, class [mscorlib]System.String>
C# syntax:     System.Collections.Generic.Dictionary<System.String, System.String>
VB.NET syntax: System.Collections.Generic.Dictionary(Of System.String, system.String)
Run Code Online (Sandbox Code Playgroud)

也许你可以调用一个语言服务来获得你想要的字符串,但你自己可能更好地生成字符串.


bob*_*mcr 6

您可以使用CodeDom生成更"正常"的C#样式声明.

CodeDomProvider csharpProvider = CodeDomProvider.CreateProvider("C#");
CodeTypeReference typeReference = new CodeTypeReference(typeof(Dictionary<string, int>));
CodeVariableDeclarationStatement variableDeclaration = new CodeVariableDeclarationStatement(typeReference, "dummy");
StringBuilder sb = new StringBuilder();
using (StringWriter writer = new StringWriter(sb))
{
    csharpProvider.GenerateCodeFromStatement(variableDeclaration, writer, new CodeGeneratorOptions());
}

sb.Replace(" dummy;", null);
Console.WriteLine(sb.ToString());
Run Code Online (Sandbox Code Playgroud)

上面的代码有以下输出:

System.Collections.Generic.Dictionary<string, int>    
Run Code Online (Sandbox Code Playgroud)

如果没有任何自定义类型字符串代码,这应该可以为您提供所需的大部分内容.