2010-02-16 18 views
6

Tôi cần phải tạo một loại từ tên đầy đủ của nó chỉ Ex: "System.String" hoặc "Tuple'2 [string, Mytype]". không có thông tin về hội đồng trong chuỗi. Đây là mã trông như thế nào.Tải một loại chung theo tên khi các đối số generics đến từ nhiều cụm

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

phương pháp này hoạt động khi loại không chung chung. Nhưng đối với các kiểu generic lặp lại thông qua các assembly luôn thất bại vì không có assembly nào chứa tất cả các định nghĩa cần thiết để xây dựng kiểu.

Có cách nào để cung cấp nhiều bộ hội thảo cho độ phân giải loại khi gọi GetTypes không?

+0

nếu bạn lập trình kéo các tên tệp và tạo tên kiểu chung để tạo, ví dụ: Ví dụ , hãy đảm bảo sử dụng AssemblyQualifiedName. –

+1

Bạn sẽ làm gì về trường hợp có hai loại trong hai tham chiếu khác nhau có cùng tên chính xác? –

+0

tất cả các loại được tiền tố với không gian tên của chúng để hy vọng điều này sẽ không xảy ra thường xuyên, việc deserialization tiếp theo sẽ thất bại. Tôi có thể quay trở lại và thử một loại khác trong một hội đồng khác và thử lại deserialization.Nhưng tôi biết nó nói dễ hơn làm. –

Trả lời

7

Bạn sẽ phải làm điều đó một cách khó khăn tôi nghĩ. May mắn thay nó không phải là khó khăn. Khá đơn giản:

  • Phân tích tên loại thành định nghĩa loại và đối số loại chung.
  • Lấy generic kiểu định nghĩa đối tượng
  • Lấy các đối tượng kiểu cho từng loại luận chung
  • Xây dựng kiểu generic ra khỏi định nghĩa kiểu generic và các đối số kiểu chung chung bằng cách sử dụng phương pháp MakeGenericType trên đối tượng kiểu định nghĩa.
+0

Tôi nghĩ về giải pháp này nhưng đó là bước cuối cùng tôi thấy khó khăn, giả sử tôi phân tích cú pháp Tuple'2 [System.String, MyNameSpace.MyType ] và tôi có thể nhận được ba loại khác nhau (Tuple, String và MyType). Làm thế nào để tôi tạo ra t instance của Type như: t == typeof (Tuple ) –

+4

Loại genericType = typeof (từ điển <,>); Gõ constructType = genericType.MakeGenericType (kiểu mới [] {typeof (String), typeof (String)}); –

+0

"Đơn giản" cho đến khi bạn thực hiện đệ quy. ;) – Lazlo

5

Something như thế này ....

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

ví dụ

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

hoặc, như Eric nói .. nếu bạn có các loại trong tay, chỉ cần xây dựng nó ..

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

* không có thông tin về lắp ráp trong chuỗi * –

+0

sau đó, trừ khi lắp ráp được tải hoặc bạn có thể tải nó VÀ không có trận đấu mơ hồ, bạn đang trong số may mắn. lấy làm tiếc. –

+0

là nó có thể buộc tải của hội đồng? –

1

Nếu định dạng là't1 [[t2, a2] [t3, a3]], a1', công trình này:

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

Dưới đây là giải pháp cách cứng của tôi để có được bất kỳ loại:

/// <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

tuyệt vời !! Cảm ơn vì điều đó – henon

Các vấn đề liên quan