.NET에서 어셈블리의 버전 관리는 현재 어셈블리의 버전을 지정하는 방법이 적어도 3 가지 있다는 점에서 혼란 스러울 수 있습니다.
다음은 세 가지 주요 버전 관련 어셈블리 속성입니다.
// 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")]
일반적으로 버전의 네 부분을 주 버전 , 부 버전 , 빌드 및 개정판이라고 합니다.
는 AssemblyFileVersion
고유의 빌드를 확인하기위한 것입니다 각각의 조립
일반적으로 어셈블리 버전을 반영하도록 Major 및 Minor AssemblyFileVersion을 수동으로 설정 한 다음 빌드 시스템이 어셈블리를 컴파일 할 때마다 빌드 및 / 또는 개정을 증가시킵니다. AssemblyFileVersion을 사용하면 어셈블리 빌드를 고유하게 식별하여 문제를 디버깅하기위한 시작점으로 사용할 수 있습니다.
현재 프로젝트에서 빌드 서버는 소스 제어 저장소의 변경 목록 번호를 AssemblyFileVersion의 빌드 및 개정 부분으로 인코딩합니다. 이를 통해 빌드 서버에서 생성 된 모든 어셈블리에 대해 어셈블리에서 소스 코드로 직접 매핑 할 수 있습니다 (소스 제어에서 레이블 또는 분기를 사용하거나 릴리스 된 버전의 레코드를 수동으로 유지하지 않아도 됨).
이 버전 번호는 Win32 버전 리소스에 저장되며 어셈블리의 Windows 탐색기 속성 페이지를 볼 때 볼 수 있습니다.
CLR은 AssemblyFileVersion을 신경 쓰거나 검사하지 않습니다.
는 AssemblyInformationalVersion
전체 제품의 버전을 표현하기위한 것입니다
AssemblyInformationalVersion은 전체 제품의 일관된 버전 관리를 허용하기위한 것으로, 버전 관리 정책이 다르거 나 개별 팀에서 개발 한 여러 버전으로 독립적으로 버전이 지정된 여러 어셈블리로 구성 될 수 있습니다.
예를 들어, 제품 버전 2.0에는 여러 어셈블리가 포함될 수 있습니다. 이 어셈블리 중 하나는 버전 1.0으로 표시되어 동일한 제품의 버전 1.0에 포함되지 않은 새 어셈블리이기 때문입니다. 일반적으로이 버전 번호의 주요 부분과 부 부분은 제품의 공개 버전을 나타내도록 설정합니다. 그런 다음 모든 조립품으로 완전한 제품을 포장 할 때마다 제작 및 수정 부품을 증가시킵니다.” — Jeffrey Richter, [C # (제 2 판)을 통한 CLR] p. 57
CLR은 AssemblyInformationalVersion을 신경 쓰거나 검사하지 않습니다.
는 AssemblyVersion
유일한 버전에 대한 CLR의 염려 (그러나 그것은 전체에 대한 관심 AssemblyVersion
)
AssemblyVersion은 CLR에서 강력한 이름의 어셈블리에 바인딩하는 데 사용됩니다. 빌드 된 어셈블리의 AssemblyDef Manifest 메타 데이터 테이블 및이를 참조하는 어셈블리의 AssemblyRef 테이블에 저장됩니다.
강력한 이름의 어셈블리를 참조 할 때 해당 어셈블리의 특정 AssemblyVersion에 밀접하게 바인딩되어 있기 때문에 이것은 매우 중요합니다. 바인딩이 성공하려면 전체 AssemblyVersion이 정확히 일치해야합니다. 예를 들어, 빌드 타임에 강력한 이름의 어셈블리 버전 1.0.0.0을 참조하지만 런타임에 해당 어셈블리의 버전 1.0.0.1 만 사용할 수있는 경우 바인딩이 실패합니다! 그런 다음 어셈블리 바인딩 리디렉션을 사용하여이 문제를 해결해야합니다 .
전체 AssemblyVersion
가 일치 해야하는지에 대한 혼란 . (그렇습니다)
어셈블리를로드하기 위해 전체 AssemblyVersion이 정확히 일치해야하는지에 대해 약간의 혼동이 있습니다. 어떤 사람들은 구속력을 얻기 위해 AssemblyVersion의 Major와 Minor 부분 만 일치해야한다는 잘못된 믿음 아래 있습니다. 이것은 현명한 가정이지만 궁극적으로 (.NET 3.5 기준) 올바르지 않으며 CLR 버전에 대해 이것을 확인하는 것은 쉽지 않습니다. 이 샘플 코드를 실행 하십시오 .
내 컴퓨터에서 두 번째 어셈블리로드가 실패하고 퓨전 로그의 마지막 두 줄이 이유를 완벽하게 알 수 있습니다.
.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.
이 혼란의 근원은 아마도 Microsoft가 원래 Major 및 Minor 버전 부분에서만 일치시킴으로써 전체 AssemblyVersion의 엄격한 일치에 대해 조금 더 관대하게 의도했기 때문일 것입니다.
"조립품을로드 할 때 CLR은 요청 된 조립품의 주 / 부 버전과 일치하는 최신 설치 서비스 버전을 자동으로 찾습니다." — Jeffrey Richter, [C # (제 2 판)을 통한 CLR] p. 56
이는 1.0 CLR 베타 1의 동작이지만이 기능은 1.0 릴리스 이전에 제거되었으며 .NET 2.0에서는 다시 표면화되지 않았습니다.
“참고 : 버전 번호를 어떻게 생각해야하는지 설명했습니다. 불행히도 CLR은이 방법으로 버전 번호를 처리하지 않습니다. [.NET 2.0]에서 CLR은 버전 번호를 불투명 한 값으로 취급하고 어셈블리가 다른 어셈블리의 버전 1.2.3.4에 의존하는 경우 CLR은 버전 1.2.3.4 만로드하려고합니다 (바인딩 리디렉션이없는 경우) ). 그러나
Microsoft는 특정 버전의 어셈블리에 대한 최신 빌드 / 리비전을로드 할 수 있도록 향후 버전에서 CLR 로더를 변경할 계획입니다.. 예를 들어, 차후 버전의 CLR에서 로더가 어셈블리의 버전 1.2.3.4를 찾고 1.2.5.0 버전이 있으면 로더는 최신 서비스 버전을 자동으로 선택합니다. 이것은 CLR 로더에 대한 매우 환영받는 변화가 될 것입니다. 저는 기다릴 수 없습니다.” — Jeffrey Richter, [C # (제 2 판)을 통한 CLR] p. 164 (공포 광산)
이 변경 사항이 아직 구현되지 않았으므로 Microsoft가이 의도를 역 추적했다고 가정하는 것이 안전하다고 생각합니다. 지금 변경하기에는 너무 늦었습니다. 웹에서 검색하여 이러한 계획으로 어떤 일이 발생했는지 알아 보려고했지만 답변을 찾을 수 없었습니다. 나는 아직도 그것의 바닥에 가고 싶었다.
그래서 Jeff Richter에게 이메일을 보냈고 직접 물어 봤습니다. 누군가 무슨 일이 있었는지 알면 그 사람이 될 것이라고 생각했습니다.
그는 12 시간 이내에 토요일 아침에 대답했으며 .NET 1.0 Beta 1 로더가 사용 가능한 최신 빌드 및 수정 어셈블리를 가져 오는이 '자동 롤 포워드'메커니즘을 구현했지만이 동작은 다음과 같습니다. .NET 1.0이 출시되기 전에 되돌 렸습니다. 나중에 이것을 되살리려 고했지만 CLR 2.0이 출시되기 전에는 만들지 않았습니다. 그런 다음 CLR 팀에 우선 순위를 둔 Silverlight가 등장하여이 기능이 더욱 지연되었습니다. 그 동안 CLR 1.0 베타 1 시절에 있었던 대부분의 사람들은 그 이후로 옮겨 왔기 때문에 이미 많은 노력을 기울 였음에도 불구하고 이것이 오늘의 빛을 볼 것 같지는 않습니다.
현재의 행동은 여기에있는 것 같습니다.
Jeff와의 논의에서 AssemblyFileVersion은 '자동 롤 포워드'메커니즘을 제거한 후에 만 추가되었다는 점에 주목할 가치가 있습니다. 1.0 베타 1 이후에는 AssemblyVersion에 대한 모든 변경 사항이 고객에게 큰 변화가 있었기 때문에 빌드 번호를 안전하게 저장할 수있는 곳이 없습니다. AssemblyFileVersion은 CLR에서 자동으로 검사하지 않으므로 안전한 피난처입니다. 아마도 AssemblyVersion의 Major / Minor (breaking) 부분과 Build / Revision (non-breaking) 부분을 분리하려고 시도하기보다는 별도의 의미를 가진 두 개의 개별 버전 번호를 갖는 것이 더 명확 할 수 있습니다.
결론 : 당신이 당신을 바꿀 때 신중하게 생각하십시오 AssemblyVersion
다른 개발자가 참조 할 어셈블리를 제공 할 경우 해당 어셈블리의 AssemblyVersion을 변경할 때 (그리고 변경하지 않을 때) 매우주의해야한다는 것이 도덕입니다. AssemblyVersion을 변경하면 응용 프로그램 개발자는 새 버전에 대해 다시 컴파일하거나 (AssemblyRef 항목을 업데이트하기 위해) 어셈블리 바인딩 리디렉션을 사용하여 바인딩을 수동으로 재정의해야합니다.
- 이전 버전과 호환되는 서비스 릴리스의 AssemblyVersion을 변경 하지 마십시오 .
- 마십시오 당신이 주요 변경 내용을 가지고 알고 릴리스에 대한 AssemblyVersion을 변경합니다.
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")]
모든 흥미로운 서비스 정보를 포함하는 것은 AssemblyFileVersion이며 (현재 사용중인 서비스 팩을 알려주는이 버전의 개정 부분 임) AssemblyVersion은 오래된 2.0.0.0으로 고정되어 있습니다. AssemblyVersion을 변경하면 mscorlib.dll을 참조하는 모든 .NET 응용 프로그램이 새 버전에 대해 다시 컴파일되도록합니다.