Làm thế nào chính xác tài sản Phiên bản cụ thể trực tuyến của một tài liệu tham khảo lắp ráp hoạt động trong Visual Studio?


155

Hôm nay tôi đã xem xét kỹ hơn về thuộc tính "Phiên bản cụ thể" của các tham chiếu lắp ráp trong Visual Studio 2010. Sau một vài thử nghiệm với kết quả không mong muốn, tôi bắt đầu tìm hiểu càng nhiều càng tốt về cách thức hoạt động của tài sản. Ngay cả SO, nó xuất hiện với tôi, không có tất cả các câu trả lời, vì vậy đây là nỗ lực của tôi trong việc tự trả lời câu hỏi:

Làm thế nào một cách chính xác hiện "Cụ Version" tài sản của một tác phẩm tham khảo lắp ráp trong Visual Studio?

Câu trả lời:


254

Đó là một tài sản thời gian biên dịch!

Một trong những điều quan trọng nhất cần biết là "Phiên bản cụ thể" là một thuộc tính có hiệu lực vào thời gian biên dịchkhông phải trong thời gian chạy.

Cái này chủ yếu là gì?

Khi một dự án được xây dựng, các tham chiếu lắp ráp của dự án cần phải được giải quyết để tìm các tổ hợp vật lý mà hệ thống xây dựng nên sử dụng. Nếu kiểm tra "Phiên bản cụ thể" được thực hiện (xem phần "Khi nào" Phiên bản cụ thể "được chọn?"), Nó sẽ ảnh hưởng đến kết quả của quá trình phân giải lắp ráp:

  • Hệ thống xây dựng định vị một tổ hợp vật lý mà nó có khả năng có thể sử dụng
  • Hệ thống xây dựng so sánh phiên bản lắp ráp vật lý với phiên bản lắp ráp được lưu trữ trong tệp .csproj để tham chiếu lắp ráp
  • Nếu hai phiên bản lắp ráp hoàn toàn giống nhau, quá trình phân giải thành công và lắp ráp vật lý được tìm thấy được sử dụng cho bản dựng
  • Nếu hai phiên bản lắp ráp không khớp nhau, lắp ráp vật lý sẽ bị loại bỏ và quá trình phân giải tiếp tục bằng cách xác định vị trí lắp ráp tiềm năng tiếp theo
  • Nếu không thể lắp ráp vật lý tiềm năng hơn nữa, quá trình giải quyết thất bại. Điều này dẫn đến một cảnh báo trình biên dịch (cảnh báo MSB3245) cho bạn biết rằng tham chiếu không thể được giải quyết.
  • Thật thú vị, việc xây dựng sau đó tiếp tục! Nếu mã không có tham chiếu thực tế đến lắp ráp, quá trình xây dựng thành công (với cảnh báo được đề cập trước đó). Nếu mã có tham chiếu, bản dựng không thành công với lỗi trông như thể mã đang sử dụng các kiểu hoặc không gian tên không xác định. Dấu hiệu duy nhất tại sao bản dựng thực sự thất bại là cảnh báo MSB3245.

Thứ tự trong đó các hội đồng được giải quyết

Thứ tự trong đó quá trình phân giải lắp ráp xác định vị trí lắp ráp tiềm năng là:

  1. Tập hợp được tham chiếu bởi <HintPath>phần tử trong tệp .csproj
  2. Đường dẫn đầu ra của dự án
  3. GAC

Lưu ý rằng nếu một số phiên bản của hội đồng tồn tại trong GAC, trước tiên, quá trình phân giải sẽ cố gắng phân giải thành phiên bản với phiên bản cao nhất. Điều này chỉ quan trọng nếu kiểm tra "Phiên bản cụ thể" không được thực hiện.

Khi nào "Phiên bản cụ thể" được kiểm tra?

Visual Studio đưa ra quyết định có nên thực hiện kiểm tra "Phiên bản cụ thể" trên hai mẩu thông tin được tìm thấy trong tệp .csproj hay không:

  • Sự hiện diện hay vắng mặt của <SpecificVersion>phần tử và giá trị của nó (nếu có)
  • Sự hiện diện hay vắng mặt của thông tin phiên bản trong tài liệu tham khảo lắp ráp

Đây là cách một tham chiếu lắp ráp điển hình với thông tin phiên bản trông như sau:

<Reference Include="Foo, Version=1.2.3.4, Culture=neutral, processorArchitecture=MSIL">
  <SpecificVersion>True</SpecificVersion>
  <HintPath>..\..\Bar\Foo.dll</HintPath>
</Reference>

Và đây là cách tham chiếu lắp ráp trông như thế nào mà không có thông tin phiên bản:

<Reference Include="Foo">
[...]

Bảng sau đây cho thấy khi kiểm tra "Phiên bản cụ thể" được thực hiện và khi nào thì không.

                            |     Version information
                            |  Present       Not present
----------------------------+------------------------------
<SpecificVersion>           |
- Present, has value True   |    Yes (1)        Yes (check always fails) (2)
- Present, has value False  |    No  (3)        No (4)
- Not present               |    Yes (5)        No (6)

Điều đáng ngạc nhiên ở đây là không có kiểm tra nào được thực hiện nếu cả hai <SpecificVersion>và thông tin phiên bản đều vắng mặt (trường hợp 6). Tôi đã mong đợi việc kiểm tra sẽ được thực hiện và luôn luôn thất bại (giống như trường hợp 2) bởi vì theo tôi hiểu sự vắng mặt của <SpecificVersion>hàm ý giá trị mặc định "Đúng". Đây có thể là một sự giải thích của Visual Studio 2010 nơi tôi đã thực hiện các bài kiểm tra của mình.

Khi bạn kiểm tra các thuộc tính của tham chiếu lắp ráp trong Giao diện người dùng Visual Studio (chọn tham chiếu và nhấn F4), giá trị bạn thấy cho thuộc tính "Phiên bản cụ thể" sẽ cho bạn biết liệu Visual Studio có thực hiện "Phiên bản cụ thể" hay không kiểm tra. Trong trường hợp 6, UI sẽ hiển thị "True", mặc dù <SpecificVersion>phần tử không có trong tệp .csproj.

Tác dụng phụ trên "Sao chép cục bộ"

Nếu thuộc tính "Sao chép cục bộ" được đặt thành "Đúng" nhưng quá trình phân giải lắp ráp không thành công do kiểm tra "Phiên bản cụ thể", không có bản sao nào được sao chép.

Tài liệu tham khảo


Cảm ơn các chi tiết. Tôi chỉ có thể kiểm tra ... kiểm tra phiên bản lắp ráp chỉ xảy ra đối với các hội đồng có tên mạnh; Có đúng không? Ngoài ra, khi chúng ta nói về việc kiểm tra phiên bản của một hội đồng - điều đó có được thực hiện bằng cách so sánh tên của hội đồng tham chiếu không? (Trong trường hợp lắp ráp có tên mạnh, tên đó bao gồm thông tin phiên bản, vì vậy nó không giống như một trường phiên bản riêng biệt được kiểm tra?)
Gavin Hope

2
@GavinITH Câu hỏi 1: Không, kiểm tra phiên bản không giới hạn ở tên mạnh, chủ yếu vì tên lắp ráp có thể bao gồm phiên bản nhưng vẫn không phải là tên mạnh (ví dụ: nếu thiếu PublicKeyToken=phần đó). Ngoài ra, nếu bạn kiểm tra bảng vào cuối bài viết của tôi, bạn có thể thấy việc kiểm tra phiên bản có thể xảy ra ngay cả khi Version=phần bị thiếu trong tên tập hợp trong .csproj. Câu 2: Tôi giả sử rằng tên lắp ráp được sử dụng để so sánh, vâng. Tôi sẽ không biết bất kỳ nguồn nào khác cho thông tin.
herzbube

"Trong trường hợp 6, giao diện người dùng sẽ hiển thị" Đúng ", mặc dù phần tử <Cụ thể> không có trong tệp .csproj." - Dường như giá trị mặc định là True . Sau khi chuyển đổi Phiên bản cụ thể trong giao diện người dùng thành True , <SpecificVersion>thẻ đã bị bỏ qua hoàn toàn, trước đây có giá trị Sai .
samis

@herzbube - Tôi nghĩ ý nghĩa của "Phiên bản cụ thể" trong Visual Studio> Cửa sổ Thuộc tính dự án trái ngược với những gì bạn đang nói ở đây (trái ngược với những gì bạn mong đợi). Visual Studio nói rằng giá trị (đúng hoặc sai) của "Phiên bản cụ thể" "cho biết liệu hội nghị này có thể được giải quyết mà không liên quan đến các quy tắc đa nhắm mục tiêu cho độ phân giải lắp ráp".
N73k

35

Khi bạn thêm một tham chiếu thì Visual Studio sẽ ghi lại [Hội đồng] của tập hợp trong tệp dự án. Điều này quan trọng. Nếu bạn, giả sử, tạo một bản sửa lỗi một năm sau đó thì bạn muốn chắc chắn rằng bạn xây dựng lại dự án với cùng một phiên bản tham chiếu chính xác để nó là một phần bổ sung thực sự. Bạn sẽ gặp lỗi nếu lắp ráp tham chiếu đã thay đổi.

Nhưng đó không phải là luôn luôn mong muốn. Một số lập trình viên để phiên bản lắp ráp tự động tăng lên, tạo ra một phiên bản mới mỗi lần họ xây dựng lại. Mặc dù giao diện công cộng của lắp ráp không bao giờ thay đổi. Một số cấu hình dự án của họ bằng cách sử dụng Nuget để có được các thư viện và để nó tự động cập nhật thư viện khi có bản phát hành mới. Họ sẽ muốn đặt thuộc tính Phiên bản cụ thể thành Sai để loại bỏ lỗi biên dịch.

Khá quan trọng để hiểu hậu quả, bạn cần phải triển khai lại toàn bộ bản dựng của chương trình để tránh tai nạn. Phiên bản không khớp khi chạy chương trình làm hỏng chương trình và chỉ có thể bị chặn bằng <bindingRedirect>tệp .config có rủi ro.


2
Cảm ơn thông tin tại sao "Phiên bản cụ thể" lại quan trọng, đây là người bạn đồng hành tốt với các khía cạnh cơ học thuần túy mà tôi đề cập trong câu trả lời của mình.
herzbube

@Hans Passant - đoạn cuối cùng của bạn có hợp lệ cho Cụ thể đúng hay sai không? Tôi nghĩ đây là những hậu quả khi bạn đặt nó thành sự thật.
GreenEyedAndy

1
Cụ thể chỉ áp dụng để xây dựng ứng dụng của bạn. Trong thời gian chạy, CLR luôn nhấn mạnh vào một kết quả khớp chính xác với số phiên bản lắp ráp tham chiếu. Nếu bạn đã sử dụng một phiên bản mới hơn vào thời gian xây dựng thì nó cũng cần phải là phiên bản mới hơn trong thời gian chạy.
Hans Passant

1
Cảnh giác với VS2013 & .Net 4.5.1 AutoGenerateBindingRedirects Họ có thể chuyển hướng liên kết dll sang phiên bản mới hơn mặc dù bạn đã bảo nó sử dụng một phiên bản cụ thể
Dennis Kuypers

1
@HansPassant Tôi nghĩ rằng CLR không tính đến [AssemblyVersion]khi các hội đồng không được ký tên mạnh.
tm1
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.