मैं स्ट्रिंग प्रतिनिधित्व से सामान्य प्रकार कैसे प्राप्त कर सकता हूं?


79

मेरे पास है MyClass<T>

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

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

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

लेकिन क्या बिना किसी पार्सिंग आदि के अंतिम प्रकार प्राप्त करने के लिए एक क्लीनर तरीका है?

जवाबों:


94

जेनरिक के लिए प्रारूप नाम, एक `चरित्र, प्रकार पैरामीटर की संख्या, कोष्ठक में प्रकार के एक अल्पविराम से सीमित सूची के द्वारा पीछा किया है:

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

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


+1 - महान जवाब, धन्यवाद! मैं यह जानने की कोशिश कर रहा था कि जेनरिक को कैसे संभाला जाए!
marc_s

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

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

38

बाहर की जाँच करें Activator.CreateInstance- आप इसे एक प्रकार से कॉल कर सकते हैं

Activator.CreateInstance(typeof(MyType))

या असेंबली और टाइप नाम के साथ string

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

यह आपको उस प्रकार का उदाहरण देगा जो आपको चाहिए।

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

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

यह आपको Typeप्रश्न में देगा।


3
यह सिर्फ एक प्रकार का उदाहरण देता है, न कि System.Type उदाहरण, जो कोड स्निपेट पर आधारित होता है, ऐसा प्रतीत होता है कि ओपी क्या देख रहा है।
डैनियल शेफ़र

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?");

1
लघु, उत्तम, अत्यंत उपयोगी! धन्यवाद
xrnd

3

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

Type mytype = Type.GetType(typeName);

इसके बाद आप इसे पास कर सकते हैं Activator.CreateInstance():

Activator.CreateInstance(mytype);

0

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

इकाई फ्रेमवर्क जेनेरिक रिपॉजिटरी त्रुटि

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

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.