Đây là a blog post I recently wrote mà đào sâu vào các chi tiết của phiên bản lắp ráp ...
Versioning của hội đồng trong .NET có thể là một triển vọng khó hiểu cho rằng hiện nay 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à các thuộc tính ba chính lắp ráp phiên bản liên quan đến:
// 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à Major Version, Tiểu Version, Xây dựng, và Bản sửa đổi.
Các AssemblyFileVersion
được thiết kế để nhận diện một xây dựng của lắp ráp cá nhân
Thông thường bạn sẽ đặt Major và Tiểu AssemblyFileVersion để phản ánh các phiên bản của hội đồng, sau đó tăng Build và/hoặc sửa đổi mỗi khi hệ thống xây dựng của bạn biên dịch hội đồng. AssemblyFileVersion sẽ cho phép bạn nhận dạng duy nhất một bản dựng của assembly, để bạn có thể sử dụng nó như là một điểm khởi đầu để gỡ rối bất kỳ vấn đề nào.
Trong dự án hiện tại của mình, chúng tôi có máy chủ xây dựng mã hóa số thay đổi từ kho kiểm soát nguồn của chúng tôi thành phần Xây dựng và sửa đổi của AssemblyFileVersion. Điều này cho phép chúng ta ánh xạ trực tiếp từ một assembly đến mã nguồn của nó, cho bất kỳ assembly nào được tạo bởi máy chủ build (không cần phải sử dụng các nhãn hoặc các nhánh trong điều khiển nguồn, hoặc tự lưu giữ bất kỳ bản ghi nào của các phiên bản đã được 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 AssemblyFileVersion.
Các AssemblyInformationalVersion
được thiết kế để đại diện cho phiên bản của toàn bộ sản phẩm của bạn
Các AssemblyInformationalVersion được thiết kế để cho phép phiên bản chặt chẽ của toàn bộ sản phẩm, trong đó có thể bao gồm nhiều hội được phiên bản độc lập, có lẽ với khác nhau chính sách versioning 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 của các hội đồng này được đánh dấu là phiên bản 1.0 vì đây là một lắp ráp mới không được giao 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ụ nhỏ của phiên bản này để đại diện cho phiên bản công khai của sản phẩm của bạn. Sau đó, bạn tăng phần xây dựng và sửa đổi mỗi lần bạn đóng gói một sản phẩm hoàn chỉnh với tất cả các cụm của nó. ” - Jeffrey Richter, CLR via C# (Second Edition) p. 57
CLR không quan tâm và cũng không kiểm tra AssemblyInformationalVersion.
Các AssemblyVersion
là phiên bản duy CLR quan tâm đến (nhưng nó quan tâm đến toàn bộ AssemblyVersion
)
Các AssemblyVersion được sử dụng bởi CLR để ràng buộc để được đặt tên mạnh hội.Nó được lưu trữ trong bảng siêu dữ liệu AssemblyDef manifest của assembly được xây dựng, và trong bảng AssemblyRef của bất kỳ assembly nào tham khảo nó.
Điều này rất quan trọng, bởi vì nó có nghĩa là khi bạn tham khảo một hội đồng được đặt tên mạnh, bạn sẽ bị ràng buộc chặt chẽ với một AssemblyVersion cụ thể của hội đồng đó. Toàn bộ AssemblyVersion phải là một kết hợp chính xác cho việc ràng buộc để 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 tên mạnh ở thời gian xây dựng, nhưng chỉ phiên bản 1.0.0.1 của hội đồng đó có sẵn khi chạy, ràng buộc sẽ không thành công! (Sau đó bạn sẽ phải giải quyết vấn đề này bằng cách sử dụng Assembly Binding Redirection.)
Lẫn lộn về việc toàn bộ số AssemblyVersion
có khớp không. (Có, đúng vậy.)
Có một chút nhầm lẫn xung quanh việc toàn bộ AssemblyVersion có phải là một kết hợp chính xác để lắp ráp được nạp hay không. Một số người dưới sự tin tưởng sai lầm rằng chỉ có các phần chính và tiểu phần của AssemblyVersion phải phù hợp để ràng buộc để thành công. Đây là một giả định hợp lý, tuy nhiên nó hoàn toàn không chính xác (như của .NET 3.5), và nó không đáng kể để xác minh điều này cho phiên bản CLR của bạn. Chỉ cần thực hiện this sample code.
Trên máy của tôi tải lắp ráp thứ hai thất bại, và hai dòng cuối cùng của nhật ký hợp làm cho nó hoàn toàn rõ ràng lý do 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à bởi vì Microsoft ban đầu dự định được một chút khoan dung hơn trên hợp chặt chẽ này của toàn bộ AssemblyVersion, bởi chỉ phù hợp trên chính và các bộ phận phiên bản nhỏ:
“Khi nạp một assembly, CLR sẽ tự động tìm phiên bản vụ cài đặt mới nhất mà 012.351.khớp với phiên bản chính/nhỏ của cụm được yêu cầu. ” - Jeffrey Richter, CLR via C# (Second Edition) p. 56
Đây là hành vi trong Beta 1 trong tổng số 1.0 CLR, tuy nhiên tính năng này đã được gỡ bỏ trước khi phát hành 1.0, và đã không được quản lý để tái mặt trong .NET 2.0:
“ Lưu ý: Tôi vừa mô tả cách bạn nên nghĩ đến số phiên bản. Thật không may, CLR không xử lý số số phiên bản theo cách này. [Trong .NET 2.0], CLR xử lý số phiên bản dưới dạng giá trị mờ và nếu assembly phụ thuộc vào phiên bản 1.2.3.4 của một phiên bản khác, CLR cố gắng tải phiên bản 1.2.3.4 chỉ (trừ khi ràng buộc chuyển hướng được đặt ra). Tuy nhiên, Microsoft có kế hoạch để thay đổi bộ nạp các CLR trong một phiên bản tương lai để nó tải các xây dựng/sửa đổi mới nhất cho một phiên bản lớn/nhỏ nhất định của một hội đồng. Ví dụ: trên phiên bản CLR trong tương lai, nếu trình tải đang cố 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 tự động nhận phiên bản dịch vụ mới nhất . Đây sẽ là thay đổi chào mừng rất đối với trình tải của CLR - Tôi để người khác không thể chờ đợi. ” - Jeffrey Richter, CLR via C# (Second Edition) p.164 (Nhấn mạnh mỏ)
Vì thay đổi này vẫn chưa được triển khai, tôi nghĩ rằng Microsoft đã theo dõi lại mục đích 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 đến tận đáy 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 đã tìm ra nếu có ai biết điều gì đã xảy ra, đó sẽ là anh ấy.
Ông trả lời trong vòng 12 giờ, vào sáng thứ Bảy không ít hơn, và làm rõ rằng trình tải lên .NET 1.0 Beta 1 đã thực hiện cơ chế 'roll-forward' tự động này để chọn Bản dựng và sửa đổi mới nhất có sẵn, nhưng hành vi này đã được hoàn nguyên trước khi .NET 1.0 xuất xưởng. Sau đó nó được thiết kế để làm sống lại điều này nhưng nó đã không được sản xuất trước khi CLR 2.0 được vận chuyển. Sau đó, đến Silverlight, ưu tiên cho nhóm CLR, vì vậy chức năng này đã bị trì hoãn thêm. Trong thời gian chờ đợi, hầu hết những người xung quanh trong những ngày CLR 1.0 Beta 1 đã tiếp tục, vì vậy không chắc rằng điều này sẽ thấy ánh sáng ban ngày, mặc dù tất cả những công việc khó khăn đã được đưa vào đó.
Hành vi hiện tại, có vẻ như, đang ở đây. Nó cũng đáng chú ý từ thảo luận của tôi với Jeff rằng AssemblyFileVersion chỉ được thêm vào sau khi loại bỏ cơ chế 'roll-forward' tự động - bởi vì sau 1.0 Beta 1, bất kỳ thay đổi nào đối với AssemblyVersion là một thay đổi đột phá cho khách hàng của bạn , sau đó không có nơi nào để lưu trữ an toàn số bản dựng của bạn. AssemblyFileVersion là nơi ẩn náu an toàn, vì nó không bao giờ được CLR kiểm tra tự động. 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 tách biệt giữa phần Chính/Nhỏ (phá vỡ) và các phần Xây dựng/Sửa đổi (không phá vỡ) của AssemblyVersion.
Điểm mấu chốt: Hãy suy nghĩ cẩn thận về khi bạn thay đổi của bạn AssemblyVersion
Các đạo đức ở đây là nếu bạn đang vận chuyển lắp ráp các nhà phát triển khác sẽ được tham khảo, bạn cần phải hết sức cẩn thận khi bạn làm (và không) thay đổi AssemblyVersion của những assembly đó. Mọi thay đổi đối với AssemblyVersion 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 AssemblyRef) hoặc sử dụng chuyển hướng ràng buộc lắp ráp để ghi đè lên ràng buộc theo cách thủ công.
- Không Thay đổi AssemblyVersion cho bản phát hành bảo trì có khả năng tương thích ngược.
- Làm thay đổi AssemblyVersion cho bản phát hành mà bạn biết đã phá vỡ các thay đổi.
Chỉ cần xem xét thêm về phiên bản thuộc tính 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à AssemblyFileVersion 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 Service Pack bạn đang ở trên), trong khi đó AssemblyVersion được cố định ở một phiên bản cũ 2.0.0.0. Mọi thay đổi đối với AssemblyVersion sẽ buộc mọi ứng dụng .NET tham chiếu đến mscorlib.dll để biên dịch lại phiên bản mới!
Tình huống: ASM - một dự án lắp ráp (.DLL/.EXE). SETUP - một dự án thiết lập. Lưu ý rằng nếu [SETUP nhắm mục tiêu ASM] VÀ [AssemblyMileVersion NOTM của ASM không được cập nhật] VÀ [binary của ASM không thay đổi (ví dụ: chỉ các tệp nội dung được cập nhật)]; Tôi đã gặp sự cố với SETUP không lấy các tệp nhị phân mới nhất (với các phiên bản mới nhất được chỉ định). Điều này gây ra các vấn đề với 'Application.ProductVersion' và khi truy cập' AssemblyInformationalVersion' thông qua sự phản chiếu. –
Đối với AssemblyFileVersion, "Nếu có thể, hãy để nó được tạo bởi MSBuild" - Tại sao? Bạn chỉ cần tiếp tục giải thích lý do chính đáng để điều khiển thủ công :) –
Cảnh báo về định dạng AssemblyInformationalVersion vẫn tồn tại trong VS2010 hôm nay (ngày 21 tháng 5 năm 2013) và liên kết của bạn đã chết. – reinierpost