2009-10-07 29 views

Trả lời

11

Ok, tôi đã thực hiện một loạt các nghiên cứu, và phát hiện ra rằng typeof (List) có "GetGenericArguments" mà sẽ giúp bạn có được các tên phụ. Vì vậy, tôi sẽ làm theo cách này (cho 1 loại chung chung, nếu nó là một đa nó sẽ mất một vòng lặp hoặc một cái gì đó. Tôi có thể gửi một chức năng cho rằng nếu được yêu cầu. . nhiều lập luận chung chung, 'lồng' kiểu generic xử lý Sửa lần nữa để làm này sử dụng chức năng tổng hợp:.

static string GetFullName(Type t) 
{ 
    if (!t.IsGenericType) 
     return t.Name; 
    StringBuilder sb=new StringBuilder(); 

    sb.Append(t.Name.Substring(0, t.Name.LastIndexOf("`"))); 
    sb.Append(t.GetGenericArguments().Aggregate("<", 

     delegate(string aggregate,Type type) 
      { 
       return aggregate + (aggregate == "<" ? "" : ",") + GetFullName(type); 
      } 
     )); 
    sb.Append(">"); 

    return sb.ToString(); 
} 
+0

Nên được tăng cường một chút. Đối số chung nên được định dạng theo cùng một cách, nó có thể là một kiểu generic một lần nữa. Tất nhiên nó phải hỗ trợ nhiều đối số chung chung. –

+0

Tôi đang trong quá trình nhập một phiên bản phức tạp hơn xử lý và bội số mà tôi vừa mới đăng. – Erich

+0

Đã chỉnh sửa lại để sử dụng tổng hợp. Kiểm tra lịch sử chỉnh sửa nếu bạn muốn phiên bản 'cũ'. Chức năng giống hệt nhau, nhưng tôi muốn tìm hiểu cách thức tổng hợp hoạt động, và đây là cách tốt để tìm hiểu :) – Erich

-1

Vâng, đó là vì tên của loại trong .NET thực sự IS List'1. "1" là cái gọi là arity của generic, và nó cho bạn biết có bao nhiêu tham số kiểu có.

Cần thiết để bạn có thể tạo thêm 1 loại chung chung với cùng một "tên" nhưng một số thông số loại chung khác.

Ví dụ: có hơn 1 loại "được gọi là" System.Action. Tên thật của chúng là System.Action'1, System.Action'2, System.Action'3, v.v.

Vì vậy, nếu bạn biết rằng loại của bạn là chung chung, bạn có thể giả định rằng có 'XX tại cuối tên, vì vậy bạn chỉ có thể cắt phần này đi, ví dụ như thế này:

string strTypeName = typeof(List<>).Name.Substring(0, typeof(List<>).Name.LastIndexOf("`")); 

PS: Vui lòng thay thế 'bằng'.

+0

Xin lỗi, đã xảy ra lỗi trong ví dụ của tôi.Tôi cần phải có được đối số của loại chung (trong ví dụ của tôi: Int32) – AndreyAkinshin

+0

Câu trả lời này không liên quan nữa (sau khi câu hỏi đã được chỉnh sửa). – ToolmakerSteve

3

Đó không phải là quá khó ;-)

được rồi, tôi sẽ cắn .. g Phần bên dưới hoạt động recusively và hiển thị các loại nguyên thủy w/o không gian tên (như OP đã viết):

static string PrettyPrintGenericTypeName(Type typeRef) 
    { 
    var rootType = typeRef.IsGenericType 
     ? typeRef.GetGenericTypeDefinition() 
     : typeRef; 

    var cleanedName = rootType.IsPrimitive 
          ? rootType.Name 
          : rootType.ToString(); 

    if (!typeRef.IsGenericType) 
     return cleanedName; 
    else 
     return cleanedName.Substring(0, 
            cleanedName.LastIndexOf('`')) 
      + typeRef.GetGenericArguments() 
        .Aggregate("<", 
           (r, i) => 
            r 
            + (r != "<" ? ", " : null) 
            + PrettyPrintGenericTypeName(i)) 
      + ">"; 
    } 

Kết quả là cleanedName trông như thế này: System.Collections.Generic.Dictionary<System.Collections.Generic.List<Int32>, ConsoleApplication2.Program+SomeType>

12

Sử dụng built-in chức năng và LINQ này có thể được viết

static string PrettyTypeName(Type t) 
{ 
    if (t.IsGenericType) 
    { 
     return string.Format(
      "{0}<{1}>", 
      t.Name.Substring(0, t.Name.LastIndexOf("`", StringComparison.InvariantCulture)), 
      string.Join(", ", t.GetGenericArguments().Select(PrettyTypeName))); 
    } 

    return t.Name; 
} 

LƯU Ý: Trong một phiên bản cũ của C#, trình biên dịch đòi hỏi rõ ràng .ToArray():

  string.Join(", ", t.GetGenericArguments().Select(PrettyTypeName).ToArray())); 
+1

Đây phải là câu trả lời được chấp nhận –

+0

Trong VS 2010 với .NET 3.5 (không chắc chắn phiên bản C# nào), 't.GetGenericArguments(). (PrettyTypeName) 'cho lỗi trình biên dịch" * không thể chuyển đổi từ 'System.Collections.Generic.IEnumerable ' thành 'string []' * "Fix: nối thêm' .ToArray() '. Thêm vào câu trả lời thay thế. – ToolmakerSteve

0

Ví dụ khác tôi đã tự viết trước khi vấp ngã ở đây.

private string PrettyPrintGenericTypeName(Type p) 
    { 
     if (p.IsGenericType) { 
      var simpleName = p.Name.Substring(0, p.Name.IndexOf('`')); 
      var genericTypeParams = p.GenericTypeArguments.Select(PrettyPrintGenericTypeName).ToList(); 
      return string.Format("{0}<{1}>", simpleName, string.Join(", ", genericTypeParams)); 
     } else { 
      return p.Name; 
     } 
    } 
0

Câu hỏi cũ, nhưng tôi chỉ có nhu cầu cho điều này ngày hôm nay. Vì vậy, tôi đã viết một phương pháp mở rộng có thể xuất tốt đẹp tìm kiếm C# định dạng chung tên có thể xử lý multilevel lồng nhau loại chung chung.

using System; 
using System.Text; 

public static class TypeExtensions 
{ 
    public static string GetNiceName(this Type type, bool useFullName = false) 
    { 
     if (!type.IsGenericType) { 
      return type.Name; 
     } 

     var typeNameBuilder = new StringBuilder(); 
     GetNiceGenericName(typeNameBuilder, type, useFullName); 
     return typeNameBuilder.ToString(); 
    } 

    static void GetNiceGenericName(StringBuilder sb, Type type, bool useFullName) 
    { 
     if (!type.IsGenericType) { 
      sb.Append(useFullName ? type.FullName : type.Name); 
      return; 
     } 

     var typeDef = type.GetGenericTypeDefinition(); 
     var typeName = useFullName ? typeDef.FullName : typeDef.Name; 
     sb.Append(typeName); 
     sb.Length -= typeName.Length - typeName.LastIndexOf('`'); 
     sb.Append('<'); 
     foreach (var typeArgument in type.GenericTypeArguments) { 
      GetNiceGenericName(sb, typeArgument, useFullName); 
      sb.Append(", "); 
     } 
     sb.Length -= 2; 
     sb.Append('>'); 
    } 
} 
Các vấn đề liên quan