.NET 4.0 có GAC mới, tại sao?


300

%windir%\Microsoft.NET\assembly\GAC mới . Điều đó có nghĩa là bây giờ chúng ta phải quản lý hai GAC, một cho các ứng dụng .NET 2.0-3.5 và một cho các ứng dụng .NET 4.0?

Câu hỏi là tại sao?


7
cảm ơn vì đã đặt câu
hỏi..tôi

2
Câu hỏi hay ... Rất cám ơn.
smwikipedia

1
+1 cho câu hỏi của bạn. Tôi bắt đầu phát triển theo NET 4.0 và bị nhầm lẫn bởi vấn đề GAC "kép" ,.
Hernán

3
Phải mất vài lần lặp lại, nhưng Microsoft cuối cùng đã mang DLL Hell đến .NET. Yay!
gì cần thiết

Câu trả lời:


181

Có vì có 2 Bộ đệm ẩn hội đồng toàn cầu (GAC) riêng biệt, bạn sẽ phải quản lý từng bộ riêng lẻ.

Trong .NET Framework 4.0, GAC đã trải qua một vài thay đổi. GAC được chia thành hai, một cho mỗi CLR.

Phiên bản CLR được sử dụng cho cả .NET Framework 2.0 và .NET Framework 3.5 là CLR 2.0. Không cần hai bản phát hành khung trước để phân chia GAC. Vấn đề phá vỡ các ứng dụng cũ hơn trong Net Framework 4.0.

Để tránh các vấn đề giữa CLR 2.0 và CLR 4.0, GAC hiện được chia thành GAC riêng cho mỗi lần chạy. Thay đổi chính là các ứng dụng CLR v2.0 hiện không thể thấy các cụm CLR v4.0 trong GAC.

Nguồn

Tại sao?

Có vẻ như là do có sự thay đổi CLR trong .NET 4.0 nhưng không phải là 2.0 thành 3.5. Điều tương tự cũng xảy ra với 1.1 đến 2.0 CLR. Có vẻ như GAC có khả năng lưu trữ các phiên bản lắp ráp khác nhau miễn là chúng đến từ cùng một CLR. Họ không muốn phá vỡ các ứng dụng cũ.

Xem thông tin sau trong MSDN về các thay đổi GAC trong 4.0 .

Ví dụ: nếu cả .NET 1.1 và .NET 2.0 chia sẻ cùng một GAC, thì ứng dụng .NET 1.1, tải một cụm từ GAC được chia sẻ này, có thể nhận các cụm .NET 2.0, do đó phá vỡ ứng dụng .NET 1.1

Phiên bản CLR được sử dụng cho cả .NET Framework 2.0 và .NET Framework 3.5 là CLR 2.0. Do đó, hai bản phát hành khung trước đó không cần phải phân chia GAC. Vấn đề phá vỡ các ứng dụng cũ hơn (trong trường hợp này là .NET 2.0) xuất hiện lại trong Net Framework 4.0 tại điểm CLR 4.0 được phát hành. Do đó, để tránh các vấn đề nhiễu giữa CLR 2.0 và CLR 4.0, GAC hiện được chia thành các GAC riêng cho mỗi lần chạy.

Vì CLR được cập nhật trong các phiên bản trong tương lai, bạn có thể mong đợi điều tương tự. Nếu chỉ có ngôn ngữ thay đổi thì bạn có thể sử dụng cùng một GAC.


18
Bài đăng trên blog đó chỉ đơn thuần nhắc lại khám phá của OP, nó không giải thích lý do tại sao GAC cần phải được chia. Không rõ ràng, GAC ban đầu hoàn toàn có khả năng tách rời các hội đồng 4.0. Họ có một [Hội đồng] mới
Hans Passant

1
@Hans: Có thể không phải là lý do chính xác nhưng nó có ghi: "Để tránh các vấn đề giữa CLR 2.0 và CLR 4.0", câu hỏi cũng có 2 câu hỏi trong đó. Câu hỏi thứ hai là: "có nghĩa là bây giờ chúng ta phải quản lý hai GAC, một cho ứng dụng .NET 2.0-3.5 và một cho ứng dụng .NET 4.0?"
Brian R. Bondy

2
Bạn nên trích dẫn điều này, từ một trong các liên kết của bạn: "Ví dụ: nếu cả .NET 1.1 và .NET 2.0 chia sẻ cùng một GAC, thì ứng dụng .NET 1.1, tải một tập hợp từ GAC được chia sẻ này, có thể nhận các tập hợp .NET 2.0 , do đó phá vỡ ứng dụng .NET 1.1. "
Max Toro

67

Tôi cũng muốn biết lý do tại sao 2 GAC và tìm thấy lời giải thích sau đây của Mark Miller trong phần bình luận của .NET 4.0 có 2 Bộ đệm ẩn toàn cầu (GAC) :

Mark Miller đã nói ... ngày 28 tháng 6 năm 2010 12:13 chiều

Cảm ơn vì bài đăng. "Vấn đề can thiệp" là mơ hồ có chủ ý. Tại thời điểm viết, các vấn đề vẫn đang được điều tra, nhưng rõ ràng có một số kịch bản bị hỏng.

Chẳng hạn, một số ứng dụng sử dụng Assemby.LoadWithPartialName để tải phiên bản cao nhất của một hội đồng. Nếu phiên bản cao nhất được biên dịch với v4, thì ứng dụng v2 (3.0 hoặc 3.5) không thể tải nó và ứng dụng sẽ bị sập, ngay cả khi có một phiên bản sẽ hoạt động. Ban đầu, chúng tôi đã phân vùng GAC theo vị trí ban đầu của nó, nhưng điều đó gây ra một số vấn đề với các kịch bản nâng cấp windows. Cả hai mã liên quan này đã được chuyển đi, vì vậy chúng tôi đã chuyển (GAC phân vùng phiên bản của chúng tôi sang một nơi khác.

Điều này sẽ không có bất kỳ tác động nào đối với hầu hết các ứng dụng và không thêm bất kỳ gánh nặng bảo trì nào. Cả hai vị trí chỉ nên được truy cập hoặc sửa đổi bằng API GAC gốc, xử lý phân vùng như mong đợi. Những nơi mà bề mặt này xuất hiện thông qua các API phơi bày các đường dẫn của GAC ​​như GetCachePath hoặc kiểm tra đường dẫn của mscorlib được tải vào mã được quản lý.

Điều đáng chú ý là chúng tôi đã sửa đổi các vị trí GAC khi chúng tôi phát hành v2 khi chúng tôi giới thiệu kiến ​​trúc như là một phần của bản sắc lắp ráp. Những người đã thêm GAC_MSIL, GAC_32 và GAC_64, mặc dù tất cả vẫn dưới% Windir% \ assembly. Thật không may, đó không phải là một lựa chọn cho phiên bản này.

Hy vọng nó sẽ giúp độc giả tương lai.


3
Nhận xét của Miller về bài viết được liên kết sẽ cung cấp một cái nhìn bên trong cho chủ đề.
Nimesh Madhavan

66

Điều đó không có ý nghĩa gì nhiều, GAC ban đầu đã hoàn toàn có khả năng lưu trữ các phiên bản lắp ráp khác nhau. Và có rất ít lý do để cho rằng một chương trình sẽ vô tình tham chiếu lắp ráp sai, tất cả các hội đồng .NET 4 có [Hội đồng] được nâng lên 4.0.0.0. Tính năng song song trong quá trình mới không nên thay đổi điều này.

Tôi đoán: đã có quá nhiều dự án .NET ngoài đó đã phá vỡ quy tắc "không bao giờ tham chiếu bất cứ điều gì trong GAC trực tiếp". Tôi đã thấy nó được thực hiện trên trang web này nhiều lần.

Chỉ có một cách để tránh phá vỡ các dự án đó: di chuyển GAC. Back-compat là thiêng liêng tại Microsoft.


3
Đây là câu trả lời duy nhất cố gắng giải thích tại sao lại như vậy. +1
Ed S.

1
@Hans Passant: Ý của bạn là gì khi không bao giờ tham khảo bất cứ điều gì trong quy tắc GAC trực tiếp "?
Max Toro

2
@Max: có hai bản sao của cụm .NET trên máy của bạn. Chúng có nghĩa là các cụm tham chiếu trong c: \ windows \ microsoft.net và c: \ chương trình tập tin \ tập hợp tham chiếu. Và những cái được sử dụng trong thời gian chạy, GAC @ c: \ windows \ assembly. Chúng không giống nhau, 64-bit sẽ là một ví dụ. Microsoft đã làm hết sức để tránh bất kỳ ai tham khảo GAC với trình xử lý mở rộng shell. Và hộp thoại Thêm tham chiếu. Không hiệu quả 100%
Hans Passant

@Hans Passant: Tham chiếu trực tiếp giống như 'c: \ WINDOWS \ assembly \ GAC_MSIL \ System \ 2.0.0.0__b77a5c561934e089 \ System.dll', tôi không thấy việc thêm phiên bản mới sẽ phá vỡ tham chiếu đó như thế nào.
Max Toro

2
@Hans Passant: "Và có rất ít lý do để cho rằng một chương trình sẽ vô tình tham chiếu lắp ráp sai" Tôi nghĩ chìa khóa ở đây là Assembly.LoadWithPartialName, điều gì xảy ra nếu chúng ta có 2 phiên bản lắp ráp trên GAC?
Max Toro
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.