2012-02-07 25 views
6

Tôi đang cố gắng sử dụng sự kiện AppDomain.AssemblyResolve để xử lý ngoại lệ trong khi giải quyết tập hợp của một số dll được tải khi chạy (SerializationException for dynamically loaded Type).Làm việc với sự kiện AppDomain.AssemblyResolve

Khi sự kiện là bắn, tôi tải tất cả các file DLL trong thư mục của mình và tạo ra một mảng Assembly, sau đó tôi sử dụng phương pháp này để có được những Assembly chứa loại I nêu rõ:

public static Assembly GetAssemblyContainingType(String completeTypeName, Assembly[] assemblies) 
    { 
     Assembly assembly = null; 

     foreach (Assembly currentassembly in assemblies) 
     { 
      Type t = currentassembly.GetType(completeTypeName, false, true); 
      if (t != null) 
      { 
       assembly = currentassembly; 
       break; 
      } 
     } 

     return assembly; 
    } 

Vấn đề là đây mã chỉ hoạt động với một số AssemblyQualifiedNameResolveEventArgs.Name do sự kiện này cung cấp không hữu ích.

Bạn có thể đề xuất cho tôi một số giải pháp khác không?

Có cách nào để chuyển một số đối số khác cho sự kiện khi sự kiện được kích hoạt không?

Trả lời

12

Bạn có thể xác định một từ điển của các hội từ thư mục của bạn, như thế này:

private readonly IDictionary<string,Assembly> additional = 
    new Dictionary<string,Assembly>(); 

tải từ điển này với cụm từ thư mục được biết đến bạn, như thế này:

foreach (var assemblyName ... corresponding to DLL names in your directory...) { 
    var assembly = Assembly.Load(assemblyName); 
    additional.Add(assembly.FullName, assembly); 
} 

Cung cấp thực hiện cho móc ...

private Assembly ResolveAssembly(Object sender, ResolveEventArgs e) { 
    Assembly res; 
    additional.TryGetValue(e.Name, out res); 
    return res; 
} 

... và móc nối tới sự kiện:

AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += ResolveAssembly; 
AppDomain.CurrentDomain.AssemblyResolve += ResolveAssembly; 

Điều này sẽ thực hiện thủ thuật.

+5

Không nạp trước các assembly có thể giảm bớt sự cần thiết cho một trình xử lý sự kiện AssemblyResolve không? –

+2

@mikez Theo như tôi biết, chỉ cần tải một assembly bằng cách sử dụng 'Assembly.Load (assemblyName)' không tự động làm cho nó có sẵn cho mã phân giải lắp ráp của miền ứng dụng của bạn (trừ khi mã đó có thể truy cập assembly bằng cách sử dụng độ phân giải mặc định quá trình). Mã này được gỡ bỏ từ một hệ thống làm việc (tôi đã xóa mã xử lý lỗi, ví dụ: xung quanh lệnh 'bổ sung.TryGetValue (e.Name, out res)' để đơn giản hóa mọi thứ một chút). Khi tôi loại bỏ móc 'ResolveAssembly', hệ thống làm việc của tôi ngừng hoạt động :) – dasblinkenlight

+2

Khi bạn đang xây dựng từ điển, hãy sử dụng AssemblyName.GetAssemblyName () thay vì Assmebly.Load để lấy tên assembly thành ánh xạ tên tệp và tránh vô điều kiện tải tất cả các hội đồng. –

0

Nếu bạn biết danh sách các hội đồng có thể chứa loại bạn đang có kế hoạch để deserialize nó có thể là tốt hơn để chỉ đơn giản là trước khi tải tất cả các hội đồng trước khi làm serialization.

Khi sự kiện AssemblyResolve được kích hoạt, bạn không có thông tin về loại gây ra tải, nhưng chỉ có tên lắp ráp. Đó là chưa rõ lý do tại sao bạn sẽ tìm kiếm lắp ráp bởi một số loại hình cụ thể trong trường hợp này. Lưu ý rằng nếu 2 hội đồng tình cờ có cùng một định danh (ví dụ: tên tệp trong trường hợp không được ký) và một sự kiện đã được tải sẽ không kích hoạt khi bạn mong đợi ngay cả khi không tìm thấy loại trong hội đã được tải. Quay lại đầu trang

Liên kết tới bài viết vì mục đích lịch sử: Resolving Assembly Loads.

+0

Như bạn cũng có thể đọc trong câu hỏi cũ của tôi http://stackoverflow.com/q/9158353/1061499 Tôi đang làm việc trên một ứng dụng sử dụng phương pháp trình cắm thêm để tải ứng dụng khác nhau của một giao diện vào thời gian chạy.Khi ứng dụng được đóng, tôi cần phải tuần tự hóa các đối tượng này, sau đó khi ứng dụng được khởi chạy lại, các đối tượng này phải được loại bỏ. Vấn đề là các kiểu đối tượng được nạp vào thời gian chạy, vì vậy kiểu của chúng không được giải quyết ... – davioooh

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