Phiên bản của các hội đồng trong .NET có thể là một viễn cảnh khó hiểu do hiện tại có ít nhất ba cách để chỉ định một phiên bản cho hội đồng của bạn.
Dưới đây là ba thuộc tính lắp ráp liên quan đến phiên bản chính:
// Assembly mscorlib, Version 2.0.0.0
[assembly: AssemblyFileVersion("2.0.50727.3521")]
[assembly: AssemblyInformationalVersion("2.0.50727.3521")]
[assembly: AssemblyVersion("2.0.0.0")]
Theo quy ước, bốn phần của phiên bản được gọi là Phiên bản chính , Phiên bản nhỏ , Bản dựng và Sửa đổi .
Mục AssemblyFileVersion
đích nhằm xác định duy nhất một bản dựng của lắp ráp riêng lẻ
Thông thường, bạn sẽ tự cài đặt MajorFileVersion theo cách thủ công để phản ánh phiên bản của hội đồng, sau đó tăng Bản dựng và / hoặc Sửa đổi mỗi khi hệ thống bản dựng của bạn biên dịch cụm. Hội đồng hội thảo sẽ cho phép bạn xác định duy nhất một bản dựng của hội đồng, để bạn có thể sử dụng nó làm điểm khởi đầu để gỡ lỗi bất kỳ vấn đề nào.
Trong dự án hiện tại của tôi, chúng tôi có máy chủ xây dựng mã hóa số lượng thay đổi từ kho lưu trữ kiểm soát nguồn của chúng tôi thành các phần Xây dựng và Sửa đổi của Hội đồngFileVersion. Điều này cho phép chúng tôi ánh xạ trực tiếp từ một cụm vào mã nguồn của nó, cho bất kỳ lắp ráp nào được tạo bởi máy chủ xây dựng (mà không phải sử dụng nhãn hoặc các nhánh trong kiểm soát nguồn hoặc giữ thủ công bất kỳ bản ghi nào của các phiên bản đã phát hành).
Số phiên bản này được lưu trữ trong tài nguyên phiên bản Win32 và có thể được nhìn thấy khi xem các trang thuộc tính Windows Explorer để lắp ráp.
CLR không quan tâm và cũng không kiểm tra hội đồngFileVersion.
Mục AssemblyInformationalVersion
đích này đại diện cho phiên bản của toàn bộ sản phẩm của bạn
Hội đồng Thông tin được thiết kế để cho phép phiên bản mạch lạc của toàn bộ sản phẩm, có thể bao gồm nhiều hội đồng được phiên bản độc lập, có thể có các chính sách phiên bản khác nhau và có khả năng được phát triển bởi các nhóm khác nhau.
Ví dụ, phiên bản 2.0 của sản phẩm có thể chứa một số cụm; một trong những hội đồng này được đánh dấu là phiên bản 1.0 vì đây là hội đồng mới không xuất xưởng trong phiên bản 1.0 của cùng một sản phẩm. Thông thường, bạn đặt các phần chính và phụ của số phiên bản này để thể hiện phiên bản công khai của sản phẩm. Sau đó, bạn tăng các phần xây dựng và sửa đổi mỗi khi bạn đóng gói một sản phẩm hoàn chỉnh với tất cả các bộ lắp ráp của nó. - Jeffrey Richter, [CLR qua C # (Ấn bản thứ hai)] p. 57
CLR không quan tâm và cũng không kiểm tra hội nghịInformalVersion.
Đây AssemblyVersion
là phiên bản duy nhất mà CLR quan tâm (nhưng nó quan tâm đến toàn bộ AssemblyVersion
)
Bộ lắp ráp được CLR sử dụng để liên kết với các cụm được đặt tên mạnh. Nó được lưu trữ trong bảng siêu dữ liệu tệp kê khai của Hội đồng được xây dựng và trong bảng Hội đồng của bất kỳ hội đồng nào tham chiếu đến nó.
Điều này rất quan trọng, bởi vì điều đó có nghĩa là khi bạn tham chiếu một hội đồng có tên mạnh mẽ, bạn bị ràng buộc chặt chẽ với một Hội đồng cụ thể của hội đồng đó. Toàn bộ Hội đồng phải là một kết hợp chính xác để liên kết thành công. Ví dụ: nếu bạn tham chiếu phiên bản 1.0.0.0 của một hội đồng có tên mạnh vào thời gian xây dựng, nhưng chỉ có phiên bản 1.0.0.1 của hội đồng đó có sẵn trong thời gian chạy, ràng buộc sẽ thất bại! (Sau đó, bạn sẽ phải xử lý vấn đề này bằng cách sử dụng Chuyển hướng kết dính .)
Nhầm lẫn về việc liệu toàn bộ AssemblyVersion
phải phù hợp. (Vâng, đúng vậy.)
Có một chút nhầm lẫn xung quanh việc liệu toàn bộ Hội đồng có phải là một kết hợp chính xác để một tập hợp được tải hay không. Một số người có niềm tin sai lầm rằng chỉ có các phần Chính và Phần phụ của Hội đồng phải khớp nhau để ràng buộc để thành công. Đây là một giả định hợp lý, tuy nhiên cuối cùng nó không chính xác (kể từ .NET 3.5) và việc xác minh điều này cho phiên bản CLR của bạn là chuyện nhỏ. Chỉ cần thực thi mã mẫu này .
Trên máy của tôi, tải lắp ráp thứ hai không thành công và hai dòng cuối cùng của nhật ký nhiệt hạch làm cho nó hoàn toàn rõ ràng tại sao:
.NET Framework Version: 2.0.50727.3521
---
Attempting to load assembly: Rhino.Mocks, Version=3.5.0.1337, Culture=neutral, PublicKeyToken=0b3305902db7183f
Successfully loaded assembly: Rhino.Mocks, Version=3.5.0.1337, Culture=neutral, PublicKeyToken=0b3305902db7183f
---
Attempting to load assembly: Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, PublicKeyToken=0b3305902db7183f
Assembly binding for failed:
System.IO.FileLoadException: Could not load file or assembly 'Rhino.Mocks, Version=3.5.0.1336, Culture=neutral,
PublicKeyToken=0b3305902db7183f' or one of its dependencies. The located assembly's manifest definition
does not match the assembly reference. (Exception from HRESULT: 0x80131040)
File name: 'Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, PublicKeyToken=0b3305902db7183f'
=== Pre-bind state information ===
LOG: User = Phoenix\Dani
LOG: DisplayName = Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, PublicKeyToken=0b3305902db7183f
(Fully-specified)
LOG: Appbase = [...]
LOG: Initial PrivatePath = NULL
Calling assembly : AssemblyBinding, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in default load context.
LOG: No application configuration file found.
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v2.0.50727\config\machine.config.
LOG: Post-policy reference: Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, PublicKeyToken=0b3305902db7183f
LOG: Attempting download of new URL [...].
WRN: Comparing the assembly name resulted in the mismatch: Revision Number
ERR: Failed to complete setup of assembly (hr = 0x80131040). Probing terminated.
Tôi nghĩ rằng nguồn gốc của sự nhầm lẫn này có lẽ là do Microsoft ban đầu dự định sẽ khoan dung hơn một chút về sự phù hợp chặt chẽ này của Hội nghị toàn diện, bằng cách chỉ khớp trên các phần của phiên bản Chính và phụ:
Khi tải một bản lắp ráp, CLR sẽ tự động tìm phiên bản dịch vụ được cài đặt mới nhất phù hợp với phiên bản chính / phụ của bản lắp ráp được yêu cầu. - Jeffrey Richter, [CLR qua C # (Ấn bản thứ hai)] p. 56
Đây là hành vi trong bản Beta 1 của 1.0 CLR, tuy nhiên tính năng này đã bị xóa trước khi phát hành 1.0 và không được quản lý để hiển thị lại trong .NET 2.0:
Lưu ý: Tôi vừa mô tả cách bạn nên nghĩ về số phiên bản. Thật không may, CLR không xử lý số phiên bản theo cách này. [Trong .NET 2.0], CLR coi số phiên bản là giá trị mờ và nếu một tổ hợp phụ thuộc vào phiên bản 1.2.3.4 của một tổ hợp khác, CLR chỉ cố gắng tải phiên bản 1.2.3.4 (trừ khi có chuyển hướng ràng buộc ). Tuy nhiên
Microsoft có kế hoạch thay đổi trình tải của CLR trong phiên bản tương lai để tải bản dựng / sửa đổi mới nhất cho phiên bản chính / phụ của một bản lắp ráp. Ví dụ, trên phiên bản tương lai của CLR, nếu trình tải đang cố gắng tìm phiên bản 1.2.3.4 của phiên bản và phiên bản 1.2.5.0 tồn tại, trình tải sẽ tự động chọn phiên bản phục vụ mới nhất. Đây sẽ là một thay đổi rất đáng hoan nghênh đối với trình tải của CLR - Tôi không thể chờ đợi. - Jeffrey Richter, [CLR qua C # (Ấn bản thứ hai)] p. 164 (mỏ nhấn mạnh)
Vì sự thay đổi này vẫn chưa được thực hiện, tôi nghĩ rằng sẽ an toàn khi cho rằng Microsoft đã theo dõi ngược lại ý định này và có lẽ đã quá muộn để thay đổi điều này ngay bây giờ. Tôi đã cố gắng tìm kiếm trên web để tìm hiểu điều gì đã xảy ra với các kế hoạch này, nhưng tôi không thể tìm thấy bất kỳ câu trả lời nào. Tôi vẫn muốn đi đến tận cùng của nó.
Vì vậy, tôi đã gửi email cho Jeff Richter và hỏi anh ấy trực tiếp - tôi đoán xem có ai biết chuyện gì đã xảy ra không, đó sẽ là anh ấy.
Anh ấy đã trả lời trong vòng 12 giờ, vào một buổi sáng thứ bảy không kém, và làm rõ rằng trình tải .NET 1.0 Beta 1 đã thực hiện cơ chế 'cuộn tự động' này để chọn bản dựng và sửa đổi mới nhất của một hội đồng, nhưng hành vi này là hoàn nguyên trước khi .NET 1.0 xuất xưởng. Sau đó, nó đã được dự định để phục hồi điều này nhưng nó đã không được thực hiện trước khi CLR 2.0 xuất xưởng. Sau đó đến Silverlight, được ưu tiên cho nhóm CLR, vì vậy chức năng này đã bị trì hoãn hơn nữa. Trong khi đó, hầu hết những người xung quanh trong thời kỳ CLR 1.0 Beta 1 đã chuyển đi, vì vậy không có khả năng điều này sẽ thấy ánh sáng ban ngày, bất chấp mọi công việc khó khăn đã được đưa vào.
Hành vi hiện tại, dường như, là ở đây.
Điều đáng chú ý từ cuộc thảo luận của tôi với Jeff rằng Hội đồngFileVersion chỉ được thêm vào sau khi loại bỏ cơ chế 'chuyển tiếp tự động' - bởi vì sau 1.0 Beta 1, mọi thay đổi đối với Hội đồng là một thay đổi đột phá đối với khách hàng của bạn, sau đó không nơi nào để lưu trữ an toàn số xây dựng của bạn. HộiFileVersion là nơi trú ẩn an toàn, vì CLR không bao giờ tự động kiểm tra. Có lẽ nó rõ ràng hơn theo cách đó, có hai số phiên bản riêng biệt, với ý nghĩa riêng biệt, thay vì cố gắng phân tách giữa phần Chính / Nhỏ (phá vỡ) và phần Xây dựng / Sửa đổi (không phá vỡ) của Hội đồng.
Điểm mấu chốt: Hãy suy nghĩ cẩn thận khi bạn thay đổi AssemblyVersion
Đạo đức là nếu bạn vận chuyển các hội đồng mà các nhà phát triển khác sẽ tham khảo, bạn cần phải cực kỳ cẩn thận khi bạn thực hiện (và không) thay đổi Hội nghị của các hội đồng đó. Bất kỳ thay đổi nào đối với Hội đồng sẽ có nghĩa là các nhà phát triển ứng dụng sẽ phải biên dịch lại phiên bản mới (để cập nhật các mục nhập của Hội đồng này) hoặc sử dụng các chuyển hướng liên kết lắp ráp để ghi đè lên ràng buộc.
- Không thay đổi Lắp ráp cho bản phát hành dịch vụ nhằm tương thích ngược.
- Đừng thay đổi AssemblyVersion cho một thông cáo mà bạn biết có thay đổi vi phạm.
Chỉ cần nhìn lại các thuộc tính phiên bản trên mscorlib:
// Assembly mscorlib, Version 2.0.0.0
[assembly: AssemblyFileVersion("2.0.50727.3521")]
[assembly: AssemblyInformationalVersion("2.0.50727.3521")]
[assembly: AssemblyVersion("2.0.0.0")]
Lưu ý rằng đó là phiên bản hội nghị có chứa tất cả các thông tin phục vụ thú vị (đó là phần Sửa đổi của phiên bản này cho bạn biết Gói dịch vụ nào bạn đang sử dụng), trong khi đó, Hội nghị được khắc phục ở phiên bản 2.0.0.0 cũ nhàm chán. Mọi thay đổi đối với Hội đồng sẽ buộc mọi ứng dụng .NET tham chiếu mscorlib.dll phải biên dịch lại so với phiên bản mới!