2009-08-30 5 views
8

मैं इस हों:.NET में जेनेरिक प्रकार के मूल नाम को प्राप्त करने का सही तरीका सबस्ट्रिंग के माध्यम से है?

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

मैं कैसे एक स्ट्रिंग के रूप "System.Collections.Generic.Dictionary" मिलता है? यह करने का सबसे अच्छा/एकमात्र तरीका है:

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

हालांकि मुझे थोड़ी सी हैकिश लगता है।

कारण मुझे यह चाहिए कि मैं Type ऑब्जेक्ट लेना चाहता हूं, और सी # स्रोत कोड फ़ाइल में पाए गए कोड के समान कोड उत्पन्न करना चाहता हूं। मैं कुछ पाठ टेम्पलेट्स उत्पादन कर रहा हूँ, और मैं स्रोत में तारों के रूप में प्रकार जोड़ने की आवश्यकता है, और 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]] 
बजाय मैं क्या चाहते हैं की

:

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

उत्तर

6

आप अधिक "सामान्य" दिखने वाले सी # -स्टाइल घोषणा उत्पन्न करने के लिए कोडडॉम का उपयोग कर सकते हैं।

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

है कि आप किसी भी कस्टम प्रकार stringifying कोड के बिना आप क्या चाहते हैं के सबसे मिलना चाहिए:

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

ऊपर कोड निम्न उत्पादन है।

2

AFAIK जेनेरिक के लिए आंतरिक नोटेशन सामान्य प्रकार के प्रकार पैरामीटर की संख्या इंगित करने के लिए `x नोटेशन का उपयोग करता है। अर्थात। 2 इंगित करता है कि शब्दकोश को बंद करने के लिए शब्दकोश को दो प्रकार की आवश्यकता है। यह ILDasm और प्रतिबिंब द्वारा उपयोग किया गया एक ही संकेत है।

+0

सही है, लेकिन है एक ही तरीका है, में प्रयोग करने से सामान्य हिस्सा पहले नाम का भाग प्राप्त करने के लिए के रूप में मैं पता चला , या वहाँ एक साफ-सुथरा प्रतिबिंब-रास्ता है, एक संपत्ति या विधि जिसके बारे में मुझे नहीं पता? –

+0

जैसा कि जोहान्सएच अपने जवाब में बताता है, आप जो देखते हैं वह आईएल नोटेशन है। अगर आप कुछ और चाहते हैं (जैसे सी #) तो आपको इसे स्वयं मैप करना होगा। हमारे पास कुछ इन-हाउस टूल्स हैं जो आप जो सुझाव दे रहे हैं उसके समान कुछ करते हैं। मुझे सी # सिंटैक्स प्राप्त करने के किसी अन्य तरीके से अवगत नहीं है, लेकिन दूसरी तरफ मैं प्रारूप को तय करने के लिए मानता हूं और इस प्रकार आप इसे सुरक्षित रूप से स्वयं को बदलने में सक्षम होना चाहिए। –

7

समस्या यह है कि आप एक भाषा विशिष्ट नोटेशन चाहते हैं, इस मामले में सी #।

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) 

शायद तुम स्ट्रिंग आप चाहते हैं पाने के लिए एक भाषा सेवा कॉल कर सकते हैं, लेकिन आप शायद स्ट्रिंग अपने आप को पैदा करने के साथ बेहतर कर रहे हैं।

+0

ठीक है, मैं कोड छोड़ दूंगा जैसा कि तब है। –

+0

एमएसडीएन दस्तावेज सी # सिंटैक्स का उपयोग करता है (शीर्षक को छोड़कर): http://msdn.microsoft.com/en-us/library/xfhwa508.aspx –

+0

@ क्रिस, आप चुन सकते हैं कि एमएसडीएन का कौन सा प्रतिनिधित्व करता है सी # होना स्क्रिप्ट-फ्री के लिए – JohannesH

3

क्या आप इसे देख रहे हैं?

यह 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(); 
} 
+0

@ जॉन: आप सही हैं, लेकिन इसका मतलब यह नहीं है कि यह उत्तर गलत है और/या डाउनवोट के योग्य है। इसके अलावा, सवाल पूछता है कि अतिरिक्त स्ट्रिंग मैनिपुलेशन के बिना इसे कैसे किया जाए, और बॉबीएमसीआर के उत्तर को अभी भी 'प्रतिस्थापन' कॉल की आवश्यकता है। – LukeH

संबंधित मुद्दे

 संबंधित मुद्दे