[.net] Visual Studio에서 어셈블리 참조의 “특정 버전”속성은 정확히 어떻게 작동합니까?

오늘은 Visual Studio 2010에서 어셈블리 참조의 “특정 버전”속성에 대해 자세히 살펴 보았습니다. 예기치 않은 결과를 몇 차례 실험 한 후 속성 작동 방식에 대해 가능한 한 많이 배웠습니다. 그렇더라도 나에게 나타나고 모든 대답이없는 것이므로 여기에 질문에 스스로 대답하려고합니다.

Visual Studio에서 어셈블리 참조의 “특정 버전”속성은 정확히 어떻게 작동합니까?



답변

컴파일 타임 속성입니다!

알아야 할 가장 중요한 사항 중 하나는 “특정 버전”에 적용됩니다 속성이라는 것이다 컴파일 시간하지 런타임에 있습니다.

무엇에 관한 것입니까?

프로젝트를 빌드 할 때 빌드 시스템이 사용해야하는 실제 어셈블리를 찾으려면 프로젝트의 어셈블리 참조를 확인해야합니다. “특정 버전”점검이 수행되면 ( “특정 버전”은 언제 점검됩니까? “섹션 참조) 조립 해결 프로세스의 결과에 영향을줍니다.

  • 빌드 시스템은 잠재적으로 사용할 수있는 물리적 어셈블리를 찾습니다
  • 빌드 시스템은 실제 어셈블리 버전을 어셈블리 참조를 위해 .csproj 파일에 저장된 어셈블리 버전과 비교합니다.
  • 두 어셈블리 버전이 정확히 동일한 경우 해결 프로세스가 성공하고 발견 된 실제 어셈블리가 빌드에 사용됩니다.
  • 두 어셈블리 버전이 일치하지 않으면 물리적 어셈블리는 삭제되고 다음 잠재적 어셈블리를 찾아 해결 프로세스가 계속됩니다.
  • 더 이상 잠재적 인 물리적 어셈블리를 찾을 수 없으면 해결 프로세스가 실패합니다. 이로 인해 참조를 확인할 수 없다는 컴파일러 경고 (경고 MSB3245)가 발생합니다.
  • 흥미롭게도 빌드가 계속됩니다! 코드에 어셈블리에 대한 실제 참조가 없으면 빌드가 완료됩니다 (이전에 언급 된 경고와 함께). 코드에 참조가 있으면 코드에서 알 수없는 형식이나 네임 스페이스를 사용하는 것처럼 보이는 오류와 함께 빌드가 실패합니다. 빌드가 실제로 실패한 유일한 이유 는 경고 MSB3245입니다.

어셈블리가 해결되는 순서

어셈블리 해결 프로세스가 잠재적 어셈블리를 찾는 순서는 다음과 같습니다.

  1. <HintPath>.csproj 파일 의 요소가 참조하는 어셈블리
  2. 프로젝트 출력 경로
  3. 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”가 표시 됩니다.

“로컬 복사”의 부작용

“로컬 복사”속성이 “참”으로 설정되어 있지만 “특정 버전”확인으로 인해 어셈블리 해결 프로세스가 실패하면 어셈블리가 복사되지 않습니다.

참고 자료


답변

참조를 추가하면 Visual Studio는 프로젝트 파일에 어셈블리의 [AssemblyVersion]을 기록합니다. 이건 중요하다. 예를 들어, 1 년 후 버그 수정을 작성한 경우 정확히 동일한 버전의 참조로 프로젝트를 다시 빌드해야합니다 . 참조 어셈블리가 변경되면 오류가 발생합니다.

그러나 항상 바람직한 것은 아닙니다. 일부 프로그래머는 어셈블리 버전을 자동으로 증가시켜 다시 빌드 할 때마다 새 버전을 생성 할 수 있습니다. 어셈블리의 공용 인터페이스는 변경되지 않았지만 일부는 Nuget을 사용하여 라이브러리를 확보하여 프로젝트를 구성하고 사용 가능한 새 릴리스가있을 때 라이브러리를 자동으로 업데이트하도록합니다. 컴파일 오류를 억제하기 위해 특정 버전 특성을 False로 설정하려고합니다.

결과를 이해하려면 매우 중요하므로 사고를 피하기 위해 프로그램의 전체 빌드를 재배치해야합니다. 런타임시 버전 불일치로 인해 프로그램이 충돌하고 <bindingRedirect>위험한 .config 파일 에서만 억제 할 수 있습니다 .


답변