2009-10-07 5 views
8

पर प्रतिबिंब का उपयोग करके सामान्य प्रारूप में जेनेरिक टाइप नाम प्राप्त करें मुझे कोड में इसकी घोषणा के रूप में सामान्य प्रकार का नाम प्राप्त करने की आवश्यकता है।सी #

उदाहरण के लिए: सूची <Int32> मैं पाने के लिए स्ट्रिंग "सूची <Int32>" चाहते हैं। स्टैंडर्ट संपत्ति टाइप करें। नाम इस स्थिति में "सूची`1" देता है।

संपादित करें: उदाहरण के

उत्तर

11

ठीक है, मैंने शोध का एक गुच्छा किया है, और पाया है कि टाइपऑफ (सूची) में "GetGenericArguments" है जो आपको उपनाम प्राप्त करेगा। तो मैं इसे इस तरह से करूँगा (1 सामान्य प्रकार के लिए, यदि यह एक बहु है तो यह एक लूप या कुछ ले जाएगा। अगर अनुरोध किया गया तो मैं उसके लिए एक फ़ंक्शन पोस्ट कर सकता हूं।

यहां ऐसा करने का एक कार्य है ।

ठीक

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

थोड़ा बढ़ाया जाना चाहिए। सामान्य तर्क को उसी तरह स्वरूपित किया जाना चाहिए, यह एक सामान्य प्रकार फिर से हो सकता है। बेशक इसे कई सामान्य तर्कों का समर्थन करना चाहिए। –

+0

मैं एक और जटिल संस्करण टाइप करने की प्रक्रिया में था जिसने इसे और गुणक को संभाला, जिसे मैंने अभी पोस्ट किया था। – Erich

+0

कुल योग का उपयोग करने के लिए फिर से संपादित किया गया। यदि आप 'पुराना' संस्करण चाहते हैं तो संपादन इतिहास देखें। कार्यक्षमता समान है, लेकिन मैं यह समझना चाहता था कि कुल कैसे काम किया गया था, और यह सीखने का एक अच्छा तरीका था :) – Erich

-1

तय किया गया था ठीक है, ऐसा इसलिए है क्योंकि .NET में प्रकार का नाम वास्तव में List'1 है। "1" जेनेरिक की तथाकथित धैर्य है, और यह आपको बताता है कि कितने प्रकार के पैरामीटर हैं।

इसकी आवश्यकता है ताकि आप एक ही "नाम" के साथ 1 सामान्य प्रकार और सामान्य प्रकार के सामान्य पैरामीटर के साथ अधिक बना सकें।

उदाहरण के लिए, 1 से अधिक प्रकार "सिस्टम" कहा जाता है। क्रिया। इनके असली नाम System.Action'1, System.Action'2, System.Action'3 आदि

इसलिए, यदि आप जानते हैं कि आपका प्रकार सामान्य है, तो आप यह मान सकते हैं कि यह 'XX है नाम का अंत, इसलिए आप इस भाग को दूर कर सकते हैं, उदाहरण के लिए:

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

पीएस: कृपया 'साथ' को प्रतिस्थापित करें।

+0

क्षमा करें, मेरे उदाहरण में एक गलती हुई थी।मुझे सामान्य प्रकार का तर्क प्राप्त करने की आवश्यकता है (मेरे उदाहरण में: Int32) – AndreyAkinshin

+0

यह उत्तर अब प्रासंगिक नहीं है (प्रश्न संपादित करने के बाद)। – ToolmakerSteve

3

भी कठिन नहीं है यही कारण है कि ;-), मैं काट देंगे ..: कई सामान्य तर्क, हैंडल 'नेस्ट' सामान्य प्रकार के फिर से संपादित इस सकल समारोह का उपयोग करने के लिए। जी नीचे दिया गया एक काम दोबारा काम करता है और आदिम प्रकारों को प्रदर्शित करता है w/o नेमस्पेस (जैसे ओपी लिखा गया है):

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)) 
      + ">"; 
    } 

जिसके परिणामस्वरूप cleanedName इस तरह दिखता है: System.Collections.Generic.Dictionary<System.Collections.Generic.List<Int32>, ConsoleApplication2.Program+SomeType>

12

बिल्ट-इन कार्य और Linq इस लिखा जा सकता है

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; 
} 

नोट का उपयोग करना: सी # के एक पुराने संस्करण में, संकलक स्पष्ट .ToArray() की आवश्यकता है:

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

यह स्वीकार्य उत्तर होना चाहिए। –

+0

वीएस 2010 में .NET 3.5 के साथ (सुनिश्चित नहीं है कि कौन सी सी # संस्करण), 'टी। गेटजेनरिक आर्ग्यूमेंट्स)। (PrettyTypeName) 'कंपाइलर त्रुटि देता है "*' System.Collections.Generic.IEnumerable 'से कनवर्ट नहीं किया जा सकता 'स्ट्रिंग []' * "फिक्स: संलग्न करें। टोएएरे()'। एक विकल्प के रूप में जवाब में जोड़ना। – ToolmakerSteve

0

एक और उदाहरण मैंने यहां खुद को ठोकर से पहले लिखा था।

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

पुराना सवाल, लेकिन मुझे केवल आज इसकी आवश्यकता है। तो मैंने एक विस्तार विधि लिखी है जो अच्छी लग रही सी # -formatted जेनेरिक नाम आउटपुट कर सकती है जो बहुस्तरीय नेस्टेड जेनेरिक प्रकारों को संभाल सकती है।

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('>'); 
    } 
}