2008-11-20 31 views
42

Tôi đang cố gắng hiểu sự khác biệt giữa Assembly.Load và Assembly.ReflectionOnlyLoad.C# Assembly.Load vs Assembly.ReflectionOnlyLoad

Trong đoạn mã dưới đây, tôi đang cố gắng để tìm thấy tất cả các đối tượng trong một hội đồng cho rằng kế thừa từ một giao diện cho:

var myTypes = new List<Type>(); 

var assembly = Assembly.Load("MyProject.Components"); 

foreach (var type in assembly.GetTypes()) 
{ 
    if (type.GetInterfaces().Contains(typeof(ISuperInterface))) 
    { 
     myTypes.Add(type); 
    } 
} 

Mã này hoạt động tốt đối với tôi, nhưng tôi đã làm một số nghiên cứu khác có thể lựa chọn thay thế tốt hơn và đi qua phương thức Assembly.ReflectionOnlyLoad().

Tôi cho rằng kể từ khi tôi đang không tải hoặc thực hiện bất kỳ của các đối tượng, về cơ bản chỉ truy vấn về định nghĩa của chúng tôi có thể sử dụng ReflectionOnlyLoad cho một sự gia tăng hiệu suất nhẹ ...

Nhưng nó chỉ ra rằng khi tôi thay đổi Assembly.Load để Assembly.ReflectionOnlyLoad tôi nhận được lỗi sau khi nó gọi assembly.GetTypes():

System.Reflection.ReflectionTypeLoadException: 

Không thể tải một hoặc nhiều các loại yêu cầu. Truy lục thuộc tính Tải trọng ngoại lệ để biết thêm thông tin .

Tôi giả định rằng mã ở trên CHỈ là phản ánh và "nhìn vào" thư viện ... nhưng đây là một ví dụ nào đó của Nguyên lý bất định Heisenberg, theo đó nhìn vào thư viện và các đối tượng trong thực tế cố gắng để khởi tạo chúng theo một cách nào đó?

Cảm ơn, Max

Trả lời

23

Theo trả lời của Jon, nó sẽ rất hữu ích để biết những gì trong LoaderExceptions. Thay cho thông tin này, tôi nghĩ tôi có thể gây nguy hiểm. Từ MSDN:

Nếu assembly có phụ thuộc, phương pháp ReflectionOnlyLoad không tải chúng. Nếu bạn cần kiểm tra chúng, bạn phải tự tải chúng.

Bạn cần đính kèm trình xử lý vào AppDomain.ReflectionOnlyAssemblyResolve để giúp CLR tải bất kỳ phụ thuộc nào của hội đồng bạn đang tải. Bạn đã làm điều này à?

8

Tôi tin rằng sự hiểu biết chung của bạn về sự khác biệt giữa Tải và ReflectionOnlyLoad là chính xác. Vấn đề ở đây (tôi nghĩ) là ngay cả khi chỉ cần tải một loại, CLR cần phải đọc siêu dữ liệu từ lắp ráp loại chính nó được định nghĩa trong cũng như tải siêu dữ liệu từ mọi hội đồng tổ tiên của loại được xác định trong. Vì vậy, bạn cần phải gọi Assembly.ReflectionOnlyLoad trên tất cả các assembly xác định các loại là tổ tiên của các loại bạn đang tải.

Để đưa ra một ví dụ, giả sử bạn có lớp sau được định nghĩa trong assembly A.dll.

public class MyBase 
{ 
    public void Foo() { } 
} 

và lớp sau được định nghĩa trong lắp ráp B.dll.

public class MySubclass : MyBase 
{ 
} 

Khi bạn gọi Assembly.GetTypes on assembly B.dll, CLR sẽ cố gắng tải loại MySubclass và tất cả các thành viên của nó. Bởi vì phương pháp Foo được định nghĩa trong MyBase trong lắp ráp A.dll (và tồn tại hư không trong siêu dữ liệu của B.dll), CLR sẽ ném ngoại lệ tải loại nếu lắp ráp A.dll chưa được tải.

6

Phương thức ReflectionOnly là cách duy nhất bạn có thể tải một Assembly cụ thể trên đĩa để kiểm tra mà không cần phải thông qua các quy tắc Load/LoadFrom thông thường. Ví dụ, bạn có thể tải một hội đồng dựa trên đĩa với cùng một danh tính như một trong GAC. Nếu bạn đã thử điều này với LoadFrom hoặc LoadFile, thì việc lắp ráp GAC là ALWAYS được nạp.

Ngoài ra, bạn không thể gọi GetCustomAttributes (...) trên cá thể Assembly Assembly trả về vì điều này sẽ cố gắng khởi tạo các thuộc tính trên assembly, đó là ReflectionOnly. Bạn phải sử dụng các phương thức tĩnh của lớp CustomAttributeData cho việc này.

Không có loại nào trong một hội đồng được tải qua ReflectionOnly có thể được khởi tạo.

1

Không có phương pháp nào có thể được thực hiện từ lắp ráp, được nạp với ReflectionOnlyLoad(), bạn sẽ nhận được InvalidOperationException. Vì vậy, đây là cách an toàn để xác định nội dung lắp ráp bằng cách sử dụng sự phản chiếu.