代码之家  ›  专栏  ›  技术社区  ›  Lasse V. Karlsen

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

  •  8
  • Lasse V. Karlsen  · 技术社区  · 16 年前

    如果我有这个:

    Type t = typeof(Dictionary<String, String>);
    

    "System.Collections.Generic.Dictionary"

    String n = t.FullName.Substring(0, t.FullName.IndexOf("`"));
    

    不过,在我看来,这有点老套。

    Type 对象,并生成与C#源代码文件中的代码类似的代码。我正在生成一些文本模板,我需要将类型作为字符串添加到源代码中 FullName property产生类似这样的结果:

    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]]
    

    而不是我想要的:

    System.Collections.Generic.Dictionary<System.String, System.String>
    

    编辑 :好的,这是最后的代码,对我来说仍然有点像黑客,但它有效:

    /// <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;
        }
    }
    
    4 回复  |  直到 10 年前
        1
  •  6
  •   bobbymcr    16 年前

    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)
    

    也许你可以调用语言服务来获取你想要的字符串,但你可能更擅长自己生成字符串。

        2
  •  7
  •   JohannesH    16 年前

    您可以使用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());
    

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

        3
  •  3
  •   LukeH    16 年前

    这更接近你想要的吗?

    它使用 CodeTypeReferenceExpression Substring Replace 电话:

    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();
    }
    
        4
  •  2
  •   Brian Rasmussen    16 年前