2009-04-06 8 views
76

मेरे पास MyClass<T> है।मैं एक स्ट्रिंग प्रतिनिधित्व से सामान्य प्रकार कैसे प्राप्त कर सकता हूं?

और फिर मेरे पास यह string s = "MyClass<AnotherClass>"; है। मैं स्ट्रिंग s से प्रकार कैसे प्राप्त कर सकता हूं?

एक ही रास्ता (बदसूरत) "<" और ">" पार्स आउट कर और क्या करना है:

Type acType = Type.GetType("AnotherClass"); 
Type whatIwant = typeof (MyClass<>).MakeGenericType(acType); 

लेकिन वहाँ कोई भी पार्सिंग, आदि के बिना एक क्लीनर तरीका अंतिम प्रकार प्राप्त करने के लिए है?

उत्तर

90

format for generics नाम, एक `चरित्र, संख्या है प्रकार पैरामीटर के बाद, ब्रैकेट्स में प्रकारों की कॉमा-सीमांकित सूची के बाद:

Type.GetType("System.Collections.Generic.IEnumerable`1[System.String]"); 

मुझे यकीन नहीं है कि सीएलआर चाहता है कि जेनरिक के लिए सी # वाक्यविन्यास से कनवर्ट करने का एक आसान तरीका है। मैंने प्रश्न में उल्लिखित जैसा विश्लेषण करने के लिए एक त्वरित रेगेक्स लिखना शुरू किया, लेकिन एहसास हुआ कि जब तक आप नेस्टेड जेनेरिक को टाइप पैरामीटर के रूप में रखने की क्षमता छोड़ नहीं देते हैं तो पार्सिंग बहुत जटिल हो जाएगी।

+0

+1 - महान जवाब, धन्यवाद! मैं जेनेरिकों को संभालने का तरीका जानने के लिए चारों ओर झुका रहा था! –

+0

धन्यवाद। यह काम करता है और मुझे इस तरह स्ट्रिंग को प्रारूपित करने के लिए कोड को संशोधित करना होगा। हालांकि, यह सोच रहा था कि अभी भी उपयोग करने का कोई तरीका है: "MyClass " टाइप उदाहरण प्राप्त करने के लिए स्ट्रिंग में बिल्कुल दिखाया गया है। बहुत साफ दिखता है। – DeeStackOverflow

+0

आपको स्ट्रिंग को इस तरह से प्रारूपित करने के लिए कोड को संशोधित करने की आवश्यकता नहीं है, बस टाइप पर ToString() पर कॉल करें। –

38

चेक बाहर Activator.CreateInstance - आप के रूप में string

Activator.CreateInstance("myAssembly", "myType") 

यह एक प्रकार

Activator.CreateInstance(typeof(MyType)) 

या एक विधानसभा और प्रकार नाम के साथ से कॉल करने की आप प्रकार आप की जरूरत का एक उदाहरण दे देंगे कर सकते हैं।

आप उदाहरण से Type बल्कि जरूरत है, Type.GetType() विधि और प्रकार आप में रुचि रखते हैं की पूरी तरह से योग्य नाम, उदाहरण के लिए उपयोग करें:

string s = "System.Text.StringBuilder"; 
Type myClassType = Type.GetType(s); 

है कि आप Type प्रश्न में दे देंगे ।

+2

यह सिर्फ प्रकार, नहीं एक System.Type उदाहरण है, जो कोड स्निपेट के आधार पर की एक आवृत्ति हो जाता है, क्या ओपी हो रहा है तलाश में है। –

0

मेरे पास इस माध्यम से विश्लेषण करने के लिए अधिक समय नहीं है, हालांकि मुझे लगता है कि मैंने कुछ समान उत्तरों को देखा है। विशेष रूप से, मुझे लगता है कि वे वास्तव में क्या कर रहे हैं क्या तुम यहाँ क्या करना चाहते हैं:

Entity Framework Generic Repository Error

(String.Format("[{0}]", baseType.Name.ToString())).OfType<T>(); 

उम्मीद है कि इस मदद करता है, मुझे और अधिक विशेष रूप से जानते हैं कि अगर यह नहीं है करते हैं।

3

बस, स्ट्रिंग से प्रकार वस्तु प्राप्त करने के लिए उपयोग करें:

Type mytype = Type.GetType(typeName); 

फिर आप Activator.CreateInstance() को यह पारित कर सकते हैं:

Activator.CreateInstance(mytype); 
26

मुझे इस तरह कुछ चाहिए और मैंने आवश्यक सामान्य प्रकार के नामों को पार्स करने के लिए कुछ कोड लिखना समाप्त कर दिया। बेशक इसमें सुधार के लिए जगह है, क्योंकि यह List<string> जैसे सामान्य प्रकार के नामों की पहचान नहीं करेगा, लेकिन यह string, int[], decimal? और इस तरह के लिए ठीक है। अगर किसी को भी मदद मिलती है तो साझा करना।

public static class TypeExtensions 
{ 
    public static Type GetTypeFromSimpleName(string typeName) 
    { 
    if (typeName == null) 
     throw new ArgumentNullException("typeName"); 

    bool isArray = false, isNullable = false; 

    if (typeName.IndexOf("[]") != -1) 
    { 
     isArray = true; 
     typeName = typeName.Remove(typeName.IndexOf("[]"), 2); 
    } 

    if (typeName.IndexOf("?") != -1) 
    { 
     isNullable = true; 
     typeName = typeName.Remove(typeName.IndexOf("?"), 1); 
    } 

    typeName = typeName.ToLower(); 

    string parsedTypeName = null; 
    switch (typeName) 
    { 
     case "bool": 
     case "boolean": 
     parsedTypeName = "System.Boolean"; 
     break; 
     case "byte": 
     parsedTypeName = "System.Byte"; 
     break; 
     case "char": 
     parsedTypeName = "System.Char"; 
     break; 
     case "datetime": 
     parsedTypeName = "System.DateTime"; 
     break; 
     case "datetimeoffset": 
     parsedTypeName = "System.DateTimeOffset"; 
     break; 
     case "decimal": 
     parsedTypeName = "System.Decimal"; 
     break; 
     case "double": 
     parsedTypeName = "System.Double"; 
     break; 
     case "float": 
     parsedTypeName = "System.Single"; 
     break; 
     case "int16": 
     case "short": 
     parsedTypeName = "System.Int16"; 
     break; 
     case "int32": 
     case "int": 
     parsedTypeName = "System.Int32"; 
     break; 
     case "int64": 
     case "long": 
     parsedTypeName = "System.Int64"; 
     break; 
     case "object": 
     parsedTypeName = "System.Object"; 
     break; 
     case "sbyte": 
     parsedTypeName = "System.SByte"; 
     break; 
     case "string": 
     parsedTypeName = "System.String"; 
     break; 
     case "timespan": 
     parsedTypeName = "System.TimeSpan"; 
     break; 
     case "uint16": 
     case "ushort": 
     parsedTypeName = "System.UInt16"; 
     break; 
     case "uint32": 
     case "uint": 
     parsedTypeName = "System.UInt32"; 
     break; 
     case "uint64": 
     case "ulong": 
     parsedTypeName = "System.UInt64"; 
     break; 
    } 

    if (parsedTypeName != null) 
    { 
     if (isArray) 
     parsedTypeName = parsedTypeName + "[]"; 

     if (isNullable) 
     parsedTypeName = String.Concat("System.Nullable`1[", parsedTypeName, "]"); 
    } 
    else 
     parsedTypeName = typeName; 

    // Expected to throw an exception in case the type has not been recognized. 
    return Type.GetType(parsedTypeName); 
    } 
} 

इसका इस्तेमाल करते हुए इस लेखन के रूप में सरल है:

Type t; 

t = TypeExtensions.GetTypeFromSimpleName("string"); 
t = TypeExtensions.GetTypeFromSimpleName("int[]"); 
t = TypeExtensions.GetTypeFromSimpleName("decimal?"); 
+5

यह कोड का एक अद्भुत उपयोगी बिट है। –

+1

लघु, बिल्कुल सही, बेहद उपयोगी! धन्यवाद – xrnd

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

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