2010-04-03 29 views
8

Tôi đang sử dụng khung tùy chỉnh sử dụng phản chiếu để thực hiện GetTypeByName(string fullName) trên tên loại đủ điều kiện mà nó lấy từ cơ sở dữ liệu, để tạo một thể hiện kiểu đã nói và thêm nó vào trang, dẫn đến một loại mô-đun chuẩn.Lắp ráp không có sẵn sau khi thay đổi Web.config

GetTypeByName là một chức năng tiện ích của tôi chỉ đơn giản là lặp qua Thread.GetDomain().GetAssemblies(), sau đó thực hiện một assembly.GetType(fullName) để tìm loại có liên quan. Rõ ràng kết quả này được lưu trữ để tham khảo và tốc độ trong tương lai. Tuy nhiên, tôi đang gặp phải một số vấn đề trong đó nếu web.config được cập nhật (và trong một số trường hợp hiếm hoi hơn nếu hồ bơi ứng dụng được tái chế) thì nó sẽ mất tất cả kiến ​​thức của một số cụm, dẫn đến không có khả năng hiển thị một thể hiện của loại mô-đun. Gỡ lỗi cho thấy rằng các hội đồng bị mất nghĩa đen không tồn tại trong danh sách hội đồng chủ đề hiện tại.

Để giải quyết vấn đề này, tôi đã thêm một lần kiểm tra thứ hai hơi bẩn nhưng đệ quy thông qua các tệp DLL/thư mục/và kiểm tra xem mỗi tệp có tồn tại trong danh sách hội đồng hay không. Nếu không, nó tải nó bằng cách sử dụng Assembly.Load và sửa vấn đề ngữ cảnh nhờ 'Solving the Assembly Load Context Problem'. Điều này sẽ làm việc, chỉ có vẻ như là (và tôi biết điều này không nên có thể) một số dự án vẫn có quyền truy cập vào hội đồng bị mất, ví dụ dự án web thực tế của tôi chứ không phải là khung chính nó - và sau đó nó than phiền rằng tài liệu tham khảo trùng lặp đã được thêm vào!

Có ai từng nghe về bất cứ điều gì như thế này không, hoặc có bất kỳ ý tưởng nào tại sao một hội đồng sẽ đơn giản rơi ra khỏi sự tồn tại trên một thay đổi cấu hình? Ngắn của một giải pháp, cách giải quyết thanh lịch nhất để có được tất cả các hội đồng trong bin để tải lại là gì? Nó cần phải được tất cả trong một "hit" để các khách truy cập trang web không thấy bất kỳ sự khác biệt khác hơn là một sự chậm trễ nhỏ, do đó, một tập tin app_offline.htm là ra câu hỏi. Đổi tên một cách có lập trình một DLL trong thùng và sau đó đặt tên nó trở lại không hoạt động, nhưng yêu cầu quyền "sửa đổi" cho tài khoản người dùng IIS, mà là điên.

Cảm ơn mọi con trỏ mà cộng đồng có thể thu thập!

+0

@ tags2k Có thể đặt liên kết để tải xuống tệp dll gây ra sự cố, để kiểm tra nó với bộ phản xạ, vào thời điểm xảy ra lỗi (aka trên GetTypeByName). – Aristos

Trả lời

2

Nói chung, bạn nên tránh dựa vào những gì hội đồng hiện đang được tải trong một appdomain, vì điều đó xảy ra tự động. Thay vào đó, chỉ cần gọi System.Web.Compilation.BuildManager.GetType() thay vì Type.GetType() hoặc Assembly.GetType(). Điều này chỉ nên làm điều phù hợp với bạn và không bị ảnh hưởng bởi chu kỳ appdomain.

+0

Cảm ơn David, tôi chưa bao giờ nghe nói về lớp học đó trước đây nhưng nó chỉ giúp mông tôi lớn lên! Cảm ơn rất nhiều - đây là tiền thưởng của bạn! : D – tags2k

+0

Vui vì tôi có thể giúp! Tôi đoán chúng tôi đã không làm một công việc rất tốt tài liệu các phương pháp BuildManager khác nhau. Tôi sẽ cố gắng viết blog cho một số. :) –

+0

Mẹo hay, nhưng bạn phải làm gì nếu những gì bạn muốn là triển khai một giao diện cụ thể và không phải là loại mã hóa cụ thể, cứng? Ví dụ: 'typeof (IStuff) .IsAssignableFrom (type) &&! Type.IsInterface'. –

1

Tôi chưa bao giờ nghe nói về vấn đề này trước đây. Tôi không chắc chắn nếu điều này sẽ làm việc, như tôi chỉ mới đọc về nó trong khi nghiên cứu cách giải quyết để phụ thuộc ODAC, nhưng xác định đường dẫn thăm dò cho hội đồng có thể khắc phục vấn đề của bạn.

xem: http://msdn.microsoft.com/en-us/library/823z9h8w(VS.80).aspx

mẫu:

<configuration> 
    <runtime> 
     <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> 
     <probing privatePath="bin;bin2\subbin;bin3"/> 
     </assemblyBinding> 
    </runtime> 
</configuration> 
+0

Cảm ơn ý tưởng Jim, nhưng tiếc là điều đó không giúp ích gì. Tôi thậm chí đã cố gắng làm một bản sao của thùng và bảo nó nhìn ở đó nhưng vô ích! – tags2k

1

Tôi có một vấn đề tương tự, khi tôi cập nhật 2-5 file, web.config ether, ether file khác, và asp.net cần để tái tạo các tập tin đang chạy, sau đó một số lần đã không tìm thấy một số lớp/chức năng tồn tại trên các tập tin dll, và hệ thống của tôi không hoạt động - ném các lỗi như của bạn.

Giải pháp của tôi là tôi đặt app_offline.htm vào thư mục gốc, cập nhật, sau đó đổi tên/xóa app_offline.htm và hệ thống của tôi hoạt động tốt.

Tôi chắc chắn có liên quan đến các tệp đã được lưu trong bộ nhớ cache, nhưng tôi không tìm kiếm deaply chính xác nguyên nhân gây ra điều đó.

Bây giờ những gì đang thực hiện giải pháp thanh lịch nhất về vấn đề này là để gọi HttpRuntime.UnloadAppDomain và thực sự làm [workaround thanh lịch nhất để có được tất cả các hội đồng trong thùng để tải lại là những gì] của bạn ứng dụng để dừng lại và bắt đầu lại.

http://msdn.microsoft.com/en-us/library/system.web.httpruntime.unloadappdomain(VS.80).aspx

Tôi không biết nếu điều này giải quyết vấn đề của bạn, bạn cần phải thực hiện các bài kiểm tra.

lẽ trên Global.asax làm một cái gì đó như thế

void Application_Error(object sender, EventArgs e) 
{ 
    Exception ex = Server.GetLastError().GetBaseException(); 
    ...if ex is your error, and you get more than 2 ... 
    { 
    HttpRuntime.UnloadAppDomain(); 
    } 
} 
+0

Cảm ơn Aristos! Thật tốt khi biết rằng tôi không phải là người duy nhất!Về giải pháp của bạn, tôi đã thử triển khai điều này trước khi có chuyển hướng ngay trước cuộc gọi để khách truy cập kích hoạt tải lại không nhận thấy bất kỳ điều gì ngoại trừ một sự chậm trễ nhỏ trong khi ứng dụng bắt đầu. Tuy nhiên, tôi không chắc liệu cuộc gọi UnloadAppDomain có thực hiện công việc khi tôi nhận được trang "Chuyển đến đối tượng ở đây", không tải trang web của tôi hay không. Tôi sẽ cung cấp cho phương pháp này một shot. – tags2k

+0

có vui lòng thực hiện một thử nghiệm về phương pháp này. Tôi đã thực hiện phương pháp này và bản thân tôi làm việc, nhưng tôi không biết điều gì xảy ra trong trường hợp của bạn. – Aristos

+0

Hi Aristos, tôi đã thử điều này một lần nữa nhưng đã có cùng một vấn đề - không có chuyển hướng tôi nhận được lỗi; nếu tôi chuyển hướng người dùng thì tôi sẽ nhận được trang "đối tượng được chuyển đến đây". Cảm ơn vì đầu vào của bạn. – tags2k

2

Như bạn biết rõ ràng, there are many situations where the current appdomain is unloaded and reloaded. Sau mỗi lần tải lại, tất cả các assembly đều được nạp và toàn bộ ứng dụng bắt đầu chạy "từ đầu".

Hội đồng theo mặc định được tải theo yêu cầu. Thường thì đó là trường hợp khi JIT tình cờ gặp một số tham chiếu. Kết quả là, một appdomain reload sẽ xóa các assembly trong appdomain và chúng sẽ chỉ xuất hiện trở lại sau khi JIT tải chúng.

Là giải pháp tôi muốn sử dụng phương thức tĩnh Type.GetType() và cung cấp tên hội đủ điều kiện (ví dụ: tên loại có tên lắp ráp được bao gồm). Đó là điều tương tự mà khung công tác sử dụng khi tải các loại được chỉ định trong tệp cấu hình và nó sẽ đảm bảo rằng hội đồng được yêu cầu được tìm kiếm và tải theo yêu cầu mà không sử dụng bất kỳ thủ thuật nào. Xem phần nhận xét của phương pháp trên (tên phương thức trên tên là một liên kết).

Điều này sẽ yêu cầu cập nhật cơ sở dữ liệu của bạn để giữ các tên hội đủ điều kiện thay vì "chỉ" tên loại đủ điều kiện. Tuy nhiên, nó cũng đảm bảo rằng bạn không chạy vào va chạm tên khi hai hội đồng cung cấp loại khác nhau với cùng tên, vì vậy đây là một ý tưởng tốt dù sao tôi nghĩ.

+0

Vấn đề của tôi với việc sử dụng 'Type.GetType()' (và lý do tôi không quyết định trong giai đoạn thiết kế ban đầu) là nếu tôi lưu trữ tên kiểu của phiên bản 1.1.0.0 của một assembly và sau đó nâng cấp lên phiên bản 1.1.0.1, tôi không có mô-đun nào trước đây hoạt động. Khi tôi không thể tải kiểu nữa vì đó là một phiên bản khác, tôi phải sử dụng các thủ thuật bẩn thỉu hơn để tham chiếu lại các mô-đun đến đúng phiên bản. Có cách nào để lưu trữ không gian tên sao cho nó sẽ cho phép bất kỳ phiên bản tương lai nào của assembly không? – tags2k

+0

Có, chỉ cần thoát khỏi phiên bản. Điều này sẽ ít nhất là làm việc cho các hội đồng mà không phải là tên mạnh. Hoặc bạn có thể thêm chuyển hướng phiên bản lắp ráp thông qua chính sách. http://msdn.microsoft.com/en-us/library/7wd6ex19.aspx – Lucero

+0

Theo như thông tin phiên bản đi .net liên kết với phiên bản lắp ráp của một dll, nơi các cửa sổ và MSI sử dụng Phiên bản Tệp. Bạn có thể tăng phiên bản tệp độc lập với phiên bản lắp ráp sao cho liên kết .net sẽ không bị ngắt sau mỗi lần tạo mới. Ví dụ: Số phiên bản lắp ráp của bạn có thể ở mức 1.1.0.0 và số phiên bản tệp của bạn có thể tăng số bản dựng sau mỗi lần tạo. –

0

Tôi sẽ cố gắng tạo một số lớp cơ bản mà từ đó lắp ráp, điều thú vị cho bạn mà không cần phản ánh trên Application Start để đảm bảo nó được tải. Ví dụ:

var temp = new BaseModuleBuilder(); 

Điều này không thông minh, nhưng rất hẹp và asp.net nên làm mọi thứ cho bạn. Trong trường hợp danh sách của bạn quá động, có thể là một cái gì đó như:

var temp = Activator.CreateInstance(Type.GetType("BaseModuleBuilder, Modules.dll")); 

Đảm bảo luôn luôn chỉ định DLL khi làm việc với các lớp được tải theo dynacmically.

+0

Cảm ơn Sergey, nhưng điều đó là không thể vì nó đòi hỏi một tham chiếu lắp ráp vòng tròn! – tags2k

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