오늘은 Visual Studio 2010에서 어셈블리 참조의 “특정 버전”속성에 대해 자세히 살펴 보았습니다. 예기치 않은 결과를 몇 차례 실험 한 후 속성 작동 방식에 대해 가능한 한 많이 배웠습니다. 그렇더라도 나에게 나타나고 모든 대답이없는 것이므로 여기에 질문에 스스로 대답하려고합니다.
Visual Studio에서 어셈블리 참조의 “특정 버전”속성은 정확히 어떻게 작동합니까?
답변
컴파일 타임 속성입니다!
알아야 할 가장 중요한 사항 중 하나는 “특정 버전”에 적용됩니다 속성이라는 것이다 컴파일 시간 과 하지 런타임에 있습니다.
무엇에 관한 것입니까?
프로젝트를 빌드 할 때 빌드 시스템이 사용해야하는 실제 어셈블리를 찾으려면 프로젝트의 어셈블리 참조를 확인해야합니다. “특정 버전”점검이 수행되면 ( “특정 버전”은 언제 점검됩니까? “섹션 참조) 조립 해결 프로세스의 결과에 영향을줍니다.
- 빌드 시스템은 잠재적으로 사용할 수있는 물리적 어셈블리를 찾습니다
- 빌드 시스템은 실제 어셈블리 버전을 어셈블리 참조를 위해 .csproj 파일에 저장된 어셈블리 버전과 비교합니다.
- 두 어셈블리 버전이 정확히 동일한 경우 해결 프로세스가 성공하고 발견 된 실제 어셈블리가 빌드에 사용됩니다.
- 두 어셈블리 버전이 일치하지 않으면 물리적 어셈블리는 삭제되고 다음 잠재적 어셈블리를 찾아 해결 프로세스가 계속됩니다.
- 더 이상 잠재적 인 물리적 어셈블리를 찾을 수 없으면 해결 프로세스가 실패합니다. 이로 인해 참조를 확인할 수 없다는 컴파일러 경고 (경고 MSB3245)가 발생합니다.
- 흥미롭게도 빌드가 계속됩니다! 코드에 어셈블리에 대한 실제 참조가 없으면 빌드가 완료됩니다 (이전에 언급 된 경고와 함께). 코드에 참조가 있으면 코드에서 알 수없는 형식이나 네임 스페이스를 사용하는 것처럼 보이는 오류와 함께 빌드가 실패합니다. 빌드가 실제로 실패한 유일한 이유 는 경고 MSB3245입니다.
어셈블리가 해결되는 순서
어셈블리 해결 프로세스가 잠재적 어셈블리를 찾는 순서는 다음과 같습니다.
<HintPath>
.csproj 파일 의 요소가 참조하는 어셈블리- 프로젝트 출력 경로
- GAC
GAC에 여러 버전의 어셈블리가있는 경우 해결 프로세스는 먼저 가장 높은 버전의 어셈블리로 해결하려고 시도합니다. “특정 버전”점검이 수행되지 않은 경우에만 중요합니다.
“특정 버전”은 언제 확인됩니까?
Visual Studio는 .csproj 파일에있는 두 가지 정보를 기반으로 “특정 버전”검사를 수행할지 여부를 결정합니다.
<SpecificVersion>
요소의 유무 및 가치 (존재하는 경우)- 조립품 참조에 버전 정보의 유무
버전 정보가있는 일반적인 어셈블리 참조는 다음과 같습니다.
<Reference Include="Foo, Version=1.2.3.4, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>True</SpecificVersion>
<HintPath>..\..\Bar\Foo.dll</HintPath>
</Reference>
버전 정보가 없는 어셈블리 참조 모양은 다음과 같습니다 .
<Reference Include="Foo">
[...]
다음 표는 “특정 버전”검사가 수행 된시기와 그렇지 않은 경우를 보여줍니다.
| 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)
여기서 놀라운 점은 <SpecificVersion>
버전 정보와 버전 정보가 모두 없으면 검사가 수행되지 않는다는 것입니다 (사례 6). 내가 이해하지 못하면 <SpecificVersion>
기본값 “True” 를 의미 하기 때문에 검사가 수행되고 항상 실패 할 것으로 예상했을 것입니다 (사례 2와 동일) . 이것은 테스트를 수행 한 Visual Studio 2010의 단점 일 수 있습니다.
Visual Studio UI에서 어셈블리 참조의 속성을 검사 할 때 (참조를 선택하고 F4를 누름) “Specific Version”속성에 표시되는 값은 Visual Studio가 “Specific Version”을 수행할지 여부를 알려줍니다. 검사. 6의 경우 <SpecificVersion>
요소가 .csproj 파일에 없지만 UI에 “True”가 표시 됩니다.
“로컬 복사”의 부작용
“로컬 복사”속성이 “참”으로 설정되어 있지만 “특정 버전”확인으로 인해 어셈블리 해결 프로세스가 실패하면 어셈블리가 복사되지 않습니다.
참고 자료
- VS2005의 참조 된 어셈블리에 대해 알아야 할 사항 (blogs.msdn.com 기사)
- 어셈블리 및 버전 관리를위한 .NET 2.0의 새로운 기능 (위의 MSDN 기사를 문구까지 재현 한 codemag.com 기사이지만 어셈블리 버전 관리에 대한 몇 가지 스크린 샷과 추가 정보가 포함되어 있습니다)
답변
참조를 추가하면 Visual Studio는 프로젝트 파일에 어셈블리의 [AssemblyVersion]을 기록합니다. 이건 중요하다. 예를 들어, 1 년 후 버그 수정을 작성한 경우 정확히 동일한 버전의 참조로 프로젝트를 다시 빌드해야합니다 . 참조 어셈블리가 변경되면 오류가 발생합니다.
그러나 항상 바람직한 것은 아닙니다. 일부 프로그래머는 어셈블리 버전을 자동으로 증가시켜 다시 빌드 할 때마다 새 버전을 생성 할 수 있습니다. 어셈블리의 공용 인터페이스는 변경되지 않았지만 일부는 Nuget을 사용하여 라이브러리를 확보하여 프로젝트를 구성하고 사용 가능한 새 릴리스가있을 때 라이브러리를 자동으로 업데이트하도록합니다. 컴파일 오류를 억제하기 위해 특정 버전 특성을 False로 설정하려고합니다.
결과를 이해하려면 매우 중요하므로 사고를 피하기 위해 프로그램의 전체 빌드를 재배치해야합니다. 런타임시 버전 불일치로 인해 프로그램이 충돌하고 <bindingRedirect>
위험한 .config 파일 에서만 억제 할 수 있습니다 .