2009-07-21 31 views
10

Thực ra tôi đã cố gắng thực hiện một số loại cụm 'liên kết tĩnh', trong giải pháp của tôi. Vì vậy, tôi đã cố gắng như sau:Làm thế nào để tải assemby vào thời gian chạy trước khi sự kiện AssemblyResolve?

  • Thêm một tài liệu tham khảo để lắp ráp của tôi với CopyLocal = false
  • Thêm file .dll bản thân để giải pháp của tôi với 'liên kết Add as'
  • Thêm file .dll bản thân để nguồn lực của tôi với 'Thêm Resource' - 'Thêm Existing file'
  • Thêm một số loại ra khỏi lắp ráp của tôi vào Form1 như private MyObject temp = new MyObject();

Sau các bước tôi đã nhận FileNotFoundException như mong đợi. Vì vậy, chúng ta hãy cố gắng tải lắp ráp trong AssemblyResolveEvent với hack nhanh này

AppDomain.CurrentDomain.AssemblyResolve += (sender, e) => 
    { 
     Assembly MyAssembly = AppDomain.CurrentDomain.Load(Properties.Resources.ExternalAssembly); 
     return MyAssembly; 
    }; 

Vì vậy, công trình này! Tôi có thể tải lắp ráp của tôi từ một tập tin tài nguyên trong một AssemblyResolveEvent. Nhưng sự kiện này chỉ xảy ra, nếu nó không thể tìm thấy hội đồng của tôi ở bất cứ nơi nào khác. Nhưng làm thế nào tôi có thể nhận được lắp ráp của tôi được nạp trước khi. Net cố gắng để tìm kiếm những nơi khác nhau ??

Do các sự kiện từ Checking for Previously Referenced Assemblies tôi nghĩ rằng nó có thể tải lắp ráp trước đó vào miền và điều này sẽ được thực hiện.

tôi đã cố gắng này trong vòng program.cs bằng cách sử dụng phương pháp

static void Main() 
{ 
    LoadMyAssemblies(); 
    AppDomain.CurrentDomain.AssemblyResolve += (sender, e) => LoadMyAssemblies(); 
    Application.EnableVisualStyles(); 
    Application.SetCompatibleTextRenderingDefault(false); 
    Application.Run(new Form1()); 
} 

private static Assembly LoadMyAssemblies() 
{ 
    Assembly result = AppDomain.CurrentDomain.Load(Properties.Resources.MyStaticAssembly); 
    return result; 
} 

sau Main() Nhưng nó vẫn chạy vào ResolveEventHandler. Và tốt hơn nhiều, nếu tôi tải lại lắp ráp và xem xét AppDomain.CurrentDomain.GetAssemblies() tôi có thể thấy rằng lắp ráp của tôi được nạp hai lần !!

Vì vậy, bất kỳ ý tưởng nào tại sao hội đồng được tải của tôi sẽ không được tính đến khi nó được tải trước sự kiện AssemblyResolve ?? Với sự giúp đỡ của trình gỡ rối tôi cũng trả về một null khi cuộc gọi đến từ AssemblyResolve, nhưng trong trường hợp này tôi nhận được một FileNotFoundException như lúc đầu.

Trả lời

3

Chỉ trong trường hợp bạn không biết, có một công cụ gọi là ILMerge từ MS Nghiên cứu hợp nhất các tập hợp thành một tệp.

Ngoài ra, bạn có thể tạo các hội đồng nhiều tệp bằng cách sử dụng Assembly Linker tool.

Plus để trả lời bạn câu hỏi ban đầu, vấn đề tôi nghĩ là thời gian chạy không biết rằng lắp ráp bạn nạp bằng tay là một trong những nó cần phải tìm kiếm. Vì vậy, trong sự kiện lắp ráp giải quyết thay vì tải lắp ráp một lần nữa, chỉ cần trả lại tham chiếu đến lắp ráp mà bạn đã tự nạp.

+0

ILMerge sẽ được sử dụng trong một số trường hợp khác, nhưng trong trường hợp này, đó không phải là giải pháp 'tốt nhất'. Đưa ra trong AssemblyResolve cùng một lắp ráp trở lại cũng không phải là một giải pháp tốt, bởi vì nếu cùng một hội đồng cũng nằm trong thư mục chương trình hoặc GAC này sẽ được thực hiện và sự kiện này sẽ không được ném. – Oliver

3

Trình kết nối CLR không biết rằng LoadMyAssemblies() thực hiện điều tương tự như sự kiện AssemblyResolve, và cả hai đều cố gắng tìm kiếm cùng một assembly và tải nó.

AssemblyResolve sự kiện luôn được kích hoạt tại điểm mà tại đó Binder quyết định rằng nó đã tìm kiếm tất cả các vị trí có thể (có thể tìm kiếm được ứng dụng đó) và không thể tìm thấy kết quả phù hợp.

Điều này đặt ra câu hỏi ban đầu, đó là lý do tại sao bạn muốn liên kết tĩnh các hội đồng được quản lý của mình?Đọc chủ đề này để thảo luận nhiều về điều này Static linking advantages

Tôi sẽ tiếp tục và trả lời một phần về cách tránh đánh sự kiện AssemblyResolve 1) Đặt lắp ráp vào GAC. Theo như Binder có liên quan, GAC luôn thắng. 2) Đặt lắp ráp của bạn trong đường dẫn thăm dò và đảm bảo rằng các Binder chọn nó lên (tìm bài viết 'Làm thế nào thời gian chạy đặt cụm' trên MSDN để biết thêm về điều này).

+0

Bạn nói đúng, CLR Binder không biết gì về chức năng của tôi. Nhưng như bạn đã đề cập, nó sẽ kích hoạt sự kiện AssemblyResolve khi nó đã tìm kiếm tất cả các vị trí có thể. Nhưng điều đó không đúng! Nó chỉ không nhìn vào danh sách các assembly được nạp trong AppDomain hiện tại! Nhưng sau khi đọc này (http://msdn.microsoft.com/en-us/library/aa98tba8.aspx) nó nên xem xét ở đó. – Oliver

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