2010-02-16 14 views
6

से आते हैं जब मुझे अपने पूर्ण नाम से केवल एक प्रकार बनाना होगा: "System.String" या "Tuple'2 [string, Mytype]"। स्ट्रिंग में असेंबली के बारे में कोई जानकारी नहीं है। यहां कोड कैसा दिखता है।जेनेरिक तर्क कई असेंबली

private static Type LoadType(string typeName) 
{ 
    // try loading the type 
    Type type = Type.GetType(typeName, false); 

    if (type != null) 
     return type; 

    // if the loading was not successfull iterate all the referenced assemblies and try to load the type. 
    Assembly asm = Assembly.GetEntryAssembly(); 
    AssemblyName[] referencedAssemblies = asm.GetReferencedAssemblies(); 
    foreach (AssemblyName referencedAssemblyName in referencedAssemblies) 
    { 
     type = referencedAssembly.GetType(typeName, false); 
     if (type != null) 
      return type; 
    } 
    throw new TypeLoadException(string.Format("Could not load the Type '{0}'",typeName)); 
} 

यह विधि काम करता है जब प्रकार सामान्य नहीं होता है। लेकिन असेंबली के माध्यम से पुनरावृत्त सामान्य प्रकारों के लिए हमेशा विफल रहता है क्योंकि किसी भी असेंबली में प्रकार बनाने के लिए आवश्यक सभी परिभाषाएं होती हैं।

क्या GetTypes को कॉल करते समय प्रकार संकल्प के लिए गुणक असेंबली प्रदान करने का कोई तरीका है?

+0

यदि आप प्रोग्राम typenames खींच रहे हैं और सामान्य प्रकार का नाम munging उदाहरण के लिए एक सूची के लिए, बनाया जाना, AssemblyQualifiedName का उपयोग सुनिश्चित करें। –

+1

आप इस मामले के बारे में क्या करने जा रहे हैं जहां दो अलग-अलग संदर्भों में दो प्रकार हैं जिनके पास बिल्कुल वही नाम है? –

+0

सभी प्रकार उनके नामस्थान के साथ उपसर्ग किए गए हैं, इसलिए उम्मीद है कि यह अक्सर नहीं होगा, बाद में deserialization विफल हो जाएगा। मैं बैकट्रैक कर सकता हूं और किसी अन्य प्रकार की असेंबली में कोशिश कर सकता हूं और deserialization को पुनः प्रयास कर सकता हूं। लेकिन मुझे पता है कि यह करने से आसान कहा जाता है। –

उत्तर

7

आप इसे मुश्किल तरीके से मुझे लगता है कि क्या करना है करने के लिए जा रहे हैं। सौभाग्य से यह मुश्किल नहीं है। बहुत सरल:

  • प्रकार का नाम प्रकार परिभाषा और सामान्य प्रकार के तर्कों में पार्स करें।
  • सामान्य प्रकार परिभाषा वस्तु
  • प्रत्येक सामान्य प्रकार तर्क
  • के लिए प्रकार की वस्तुओं को प्राप्त प्राप्त सामान्य प्रकार परिभाषा और प्रकार परिभाषा वस्तु पर MakeGenericType पद्धति का उपयोग करके सामान्य प्रकार तर्क से बाहर सामान्य प्रकार का निर्माण।
+0

द्वारा दिखाए गए और वर्णित प्रकार विधियों का उपयोग करके इसे बना सकते हैं, मैंने इस समाधान के बारे में सोचा था, लेकिन यह अंतिम चरण है जो मुझे मुश्किल लगता है, मान लें कि मैंने tuple'2 को पार्स किया है [System.String, MyNameSpace.MyType ] और मैं तीन diffrents प्रकार (ट्यूपल, स्ट्रिंग और MyType) प्राप्त करने में सक्षम हूँ। मैं टाइप प्रकार का उदाहरण टी कैसे बना सकता हूं जैसे: टी == टाइपोफ (टुपल <स्ट्रिंग, माईटाइप>) –

+4

जेनेरिक टाइप टाइप करें (टाइप <,>); टाइप टाइप टाइप = जेनेरिक टाइप। मेक जेनरिक टाइप (नया प्रकार [] {टाइपोफ (स्ट्रिंग), टाइपऑफ (स्ट्रिंग)}); –

+0

"सीधे" जब तक आप खाते में रिकर्सन नहीं ले लेते। ;) – Lazlo

5

इस तरह कुछ ....

Type.GetType("namespace.typename`1[[namespace.typename, assemblyname]], assemblyname"); 

उदा

var type = Type.GetType("System.Collections.Generic.List`1[[System.String, mscorlib]], mscorlib"); 
var instance = Activator.CreateInstance(type); 

या, एरिक कहते हैं .. अगर आप हाथ में प्रकार है, बस इसे बनाने ..

Type genericType = typeof(Dictionary<,>); 
Type constructedType = genericType.MakeGenericType(new Type[] { typeof(String), typeof(String) }); 
+0

* स्ट्रिंग * –

+0

में असेंबली के बारे में कोई जानकारी नहीं है, तब तक जब तक असेंबली लोड नहीं हो जाती है या आप इसे लोड कर सकते हैं और कोई अस्पष्ट मिलान नहीं है, तो आप भाग्य से बाहर हैं। माफ़ कीजिये। –

+0

असेंबली के लोडिंग को मजबूर करना संभव है? –

1

प्रारूप't1 [[t2, a2] [t3, a3]], a1', इस काम करता है:

private Type GetAckwardType(string typeName) 
{ 
    var tokens = typeName.Split(new [] {"[[", "]]", "]["}, StringSplitOptions.None); 
    if (tokens.Length == 1) 
     return Type.GetType(typeName, true); 

    var plainType = Type.GetType(tokens[0] + tokens[tokens.Length - 1], true); 
    var args = tokens.Skip(1).Take(tokens.Length - 2).Select(_ => Type.GetType(_, true)).ToArray(); 
    return plainType.MakeGenericType(args); 
} 
2

यहाँ किसी भी प्रकार प्राप्त करने के लिए है मेरी मुश्किल तरीके से समाधान:

/// <summary> 
    /// Gets the type associated with the specified name. 
    /// </summary> 
    /// <param name="typeName">Full name of the type.</param> 
    /// <param name="type">The type.</param> 
    /// <param name="customAssemblies">Additional loaded assemblies (optional).</param> 
    /// <returns>Returns <c>true</c> if the type was found; otherwise <c>false</c>.</returns> 
    public static bool TryGetTypeByName(string typeName, out Type type, params Assembly[] customAssemblies) 
    { 
     if (typeName.Contains("Version=") 
      && !typeName.Contains("`")) 
     { 
      // remove full qualified assembly type name 
      typeName = typeName.Substring(0, typeName.IndexOf(',')); 
     } 

     type = Type.GetType(typeName); 

     if (type == null) 
     { 
      type = GetTypeFromAssemblies(typeName, customAssemblies); 
     } 

     // try get generic types 
     if (type == null 
      && typeName.Contains("`")) 
     { 
      var match = Regex.Match(typeName, "(?<MainType>.+`(?<ParamCount>[0-9]+))\\[(?<Types>.*)\\]"); 

      if (match.Success) 
      { 
       int genericParameterCount = int.Parse(match.Groups["ParamCount"].Value); 
       string genericDef = match.Groups["Types"].Value; 
       List<string> typeArgs = new List<string>(genericParameterCount); 
       foreach (Match typeArgMatch in Regex.Matches(genericDef, "\\[(?<Type>.*?)\\],?")) 
       { 
        if (typeArgMatch.Success) 
        { 
         typeArgs.Add(typeArgMatch.Groups["Type"].Value.Trim()); 
        } 
       } 

       Type[] genericArgumentTypes = new Type[typeArgs.Count]; 
       for (int genTypeIndex = 0; genTypeIndex < typeArgs.Count; genTypeIndex++) 
       { 
        Type genericType; 
        if (TryGetTypeByName(typeArgs[genTypeIndex], out genericType, customAssemblies)) 
        { 
         genericArgumentTypes[genTypeIndex] = genericType; 
        } 
        else 
        { 
         // cant find generic type 
         return false; 
        } 
       } 

       string genericTypeString = match.Groups["MainType"].Value; 
       Type genericMainType; 
       if (TryGetTypeByName(genericTypeString, out genericMainType)) 
       { 
        // make generic type 
        type = genericMainType.MakeGenericType(genericArgumentTypes); 
       } 
      } 
     } 

     return type != null; 
    } 

    private static Type GetTypeFromAssemblies(string typeName, params Assembly[] customAssemblies) 
    { 
     Type type = null; 

     if (customAssemblies != null 
      && customAssemblies.Length > 0) 
     { 
      foreach (var assembly in customAssemblies) 
      { 
       type = assembly.GetType(typeName); 

       if (type != null) 
        return type; 
      } 
     } 

     var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies(); 
     foreach (var assembly in loadedAssemblies) 
     { 
      type = assembly.GetType(typeName); 

      if (type != null) 
       return type; 
     }   

     return type; 
    } 
+0

बढ़िया !! उसके लिए धन्यवाद – henon

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