2011-11-04 19 views
7

tôi sử dụng đoạn mã sau:Làm thế nào tôi có thể nhận được một loại từ một hội đồng được tải từ bên trong một thư mục khác?

Assembly.LoadFile("the assembly in another folder"); 
var type = Type.GetType("the full name of the type"); 

Mặc dù lắp ráp đã được nạp trước khi dòng mã này, nó luôn luôn trả về null trong type.

PS: Tôi đã vượt qua trong tên hội đủ điều kiện, bao gồm không gian tên, tên loại, tên lắp ráp, phiên bản và mã thông báo công cộng.

+0

Đây có phải là 'assembly' bằng cách nào đó liên quan đến ngôn ngữ lắp ráp không? –

+0

@KirilKirov: Không. Đó là một loại trong .Net. –

+0

@Austin - ah, cảm ơn :) Tôi đã bị lừa bởi thẻ. –

Trả lời

9

Type.GetType chỉ tìm kiếm các loại trong hội đồng gọi điện và các loại trong mscorlib.dll trừ khi bạn vượt qua tên hội đủ điều kiện của loại. See here.

EDIT

Dường như Type.GetType chỉ có thể lấy Type trường từ lắp ráp trong bối cảnh Load. Các hội đồng được tải bằng cách sử dụng LoadFile nằm trong no context và các cụm được tải bằng cách sử dụng LoadFrom nằm trong ngữ cảnh Tải từ; cả hai ngữ cảnh này đều không cho phép bạn sử dụng Type.GetType để độ phân giải không thành công. This article cho thấy rằng Type thông tin có thể được truy xuất cho một Assembly khi thư mục được thêm vào dưới dạng tệp thăm dò riêng tư vì nó sau đó sẽ kết thúc trong ngữ cảnh Tải nhưng sẽ không thành công trong các ngữ cảnh khác.

+0

tôi đã vượt qua trong tên hội đủ điều kiện, bao gồm không gian tên, tên loại, tên lắp ráp và phiên bản, mã thông báo công cộng. – CuiPengFei

+0

@CuiPengFei Chỉ để loại bỏ hiển nhiên, bạn có chắc chắn rằng tên hội đủ điều kiện phù hợp chính xác giá trị nhạy cảm với trường hợp bạn sẽ nhận được nếu bạn tham chiếu tĩnh assembly và gọi 'typeof (TypeName) .AssemblyQualifiedName'? –

+0

vâng, tôi chắc chắn. – CuiPengFei

1

bạn có thể thử này ....

Assembly.GetAssembly giả sử bạn có một thể hiện của các loại, và Type.GetType giả sử bạn có loại tên đầy đủ bao gồm tên lắp ráp.

bạn có thể cho con đường mà lắp ráp nằm .....

Nếu bạn chỉ có tên loại hình cơ bản, bạn cần phải làm điều gì đó như thế này:

public static String GetAssemblyNameContainingType(String typeName) 
{ 
    foreach (Assembly currentassembly in AppDomain.CurrentDomain.GetAssemblies()) 
    { 
     Type t = currentassembly.GetType(typeName, false, true); 
     if (t != null) {return currentassembly.FullName;} 
    } 

    return "not found"; 
} 

này cũng giả định của bạn loại được khai báo trong thư mục gốc. Bạn sẽ cần phải cung cấp không gian tên hoặc các loại bao quanh trong tên, hoặc lặp lại theo cách tương tự.

+0

Hãy cẩn thận khi tải hội đồng vì một khi bạn tải chúng vào một AppDomain bạn không thể dỡ bỏ chúng nữa. Nếu bạn có rất nhiều assembly để tải suy nghĩ về việc tạo ra AppDomain riêng biệt, nó sẽ thực hiện công việc thực hiện các assembly xử lý và trả về kết quả, sau đó nó có thể được giải phóng. –

+0

Tôi sẽ không đề nghị điều này. Thay vào đó, hãy liên kết với sự kiện [AppDomain.AssemblyResolve] (http://msdn.microsoft.com/en-us/library/system.appdomain.assemblyload.aspx). Bằng cách đó, bạn chỉ trả về assembly được yêu cầu, ở đâu trong đoạn mã trên, bạn tìm kiếm _each và mọi assembly được nạp, cộng với việc bạn bắt đầu load assembly không cần thiết. – Abel

2

Cách đơn giản nhất để làm việc đó chỉ đơn giản là cái bẫy giá trị trả về của Assembly.LoadFile trong một biến và gọi GetType vào nó như thế này:

Assembly assem = Assembly.LoadFile("assemblyLocation"); 
assem.GetType("typeName"); 

Bạn có thể muốn xem xét việc giữ một tham chiếu đến assembly này nếu bạn sẽ muốn kéo các loại từ nó thường xuyên, hoặc làm những gì người khác đã gợi ý và làm cho một phương pháp chung chung hơn mà vòng qua tất cả các hội đồng được nạp.

4

Cách "thích hợp" (MS được khuyến nghị) để thực hiện việc này, khi bạn phải sử dụng Type.GetType(string) trên các loại trong các cụm không nằm trong ngữ cảnh tải nhưng trong ngữ cảnh tải từ hoặc không bối cảnh, là liên kết với Appdomain.AssemblyResolve sự kiện. Các mã sau đây là tương đối hiệu quả:

// this resolver works as long as the assembly is already loaded 
// with LoadFile/LoadFrom or Load(string)/Load(byte[]) 
private static Assembly OnAssemblyResolve(object sender, ResolveEventArgs args) 
{ 
    var asm = (from a in AppDomain.CurrentDomain.GetAssemblies() 
       where a.GetName().FullName == args.Name 
       select a).FirstOrDefault(); 

    if(asm == null) 
     throw FileNotFoundException(args.Name);  // this becomes inner exc 

    return asm; 
} 

// place this somewhere in the beginning of your app: 
AppDomain.CurrentDomain.AssemblyResolve += OnAssemblyResolve; 

Có vẻ hơi hiệu quả hơn để tạo ra một sự kết hợp của những sự kiện AssemblyLoad/Giải quyết để giữ một cuốn từ điển của assembly được nạp (sử dụng lắp ráp tên tuổi như key).

Khi được lắp ráp.LoadFile
Có một số hạn chế nghiêm trọng khi sử dụng phương pháp này. According to MSDN:

LoadFile không tải tệp vào LoadFrom context và không giải quyết các phụ thuộc bằng cách sử dụng đường dẫn tải, như phương thức LoadFrom.

Vì vậy, nếu có thể, không sử dụng LoadFile. Việc lắp ráp kết quả được nạp trong bối cảnh không bối cảnh, có nhiều hạn chế hơn so với ngữ cảnh tải-từ. Thay vào đó, hãy sử dụng Assembly.LoadFrom và các phụ thuộc sẽ được tải tự động từ đường dẫn tải.

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