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


155

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

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

답변:


255

컴파일 타임 속성입니다!

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

무엇에 관한 것입니까?

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

  • 빌드 시스템은 잠재적으로 사용할 수있는 물리적 어셈블리를 찾습니다
  • 빌드 시스템은 실제 어셈블리 버전을 어셈블리 참조를 위해 .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"가 표시 됩니다.

"로컬 복사"의 부작용

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

참고 자료


자세한 내용에 감사드립니다. 그냥 확인할 수 있습니까 ... 어셈블리 버전 검사는 강력한 이름을 가진 어셈블리에 대해서만 발생합니다. 맞습니까? 또한 어셈블리 버전 확인에 대해 이야기 할 때 참조 된 어셈블리의 이름 을 비교하여 수행 합니까? 강력한 이름의 어셈블리의 경우 해당 이름 에 버전 정보가 포함되어 있으므로 별도의 버전 필드를 확인하는 것과 같지 않습니까?
Gavin Hope

2
@GavinHope 질문 1 : 아니요, 버전 확인은 강력한 이름으로 제한되지 않습니다. 주로 어셈블리 이름에 버전이 포함될 수 있지만 여전히 강력한 이름이 아니기 때문입니다 (예 : PublicKeyToken=부품 이없는 경우 ). 또한 내 게시물 끝쪽으로 테이블을 확인 Version=하면 .csproj의 어셈블리 이름에서 부품이 누락 된 경우에도 버전 확인이 발생할 수 있음을 알 수 있습니다 . 질문 2 : 어셈블리 이름을 비교에 사용한다고 가정합니다. 나는 그 정보에 대한 다른 출처를 모른다.
herzbube

"6의 경우 <SpecificVersion> 요소가 .csproj 파일에 없지만 UI에"True "가 표시됩니다." -기본값은 True 인 것으로 보입니다 . 의 UI에서 특정 버전을 전환 한 후 진정한<SpecificVersion> 태그는 완전히 이전의 값이 있던, 생략 거짓을 .
samis

@herzbube-Visual Studio> 프로젝트 속성 창에서 "특정 버전"의 의미는 여기서 말하는 것과 반대입니다 (예상하는 것과 반대입니다). Visual Studio에 따르면 "특정 버전"의 값 (true 또는 false)은 "어셈블리 해결 위한 다중 타겟팅 규칙 과 상관없이이 어셈블리를 해결할 수 있는지 여부를 나타냅니다 ."
N73k

35

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

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

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


2
"Specific Version"이 중요한 이유 에 대한 정보 덕분에 , 이것은 내가 대답 할 순전히 기계적인 측면과 좋은 동반자입니다.
herzbube 2014 년

@Hans Passant-마지막 단락이 SpecificVersion True 또는 False에 유효합니까? 나는 이것이 당신이 그것을 true로 설정했을 때의 결과라고 생각합니다.
GreenEyedAndy

1
SpecificVersion은 앱 빌드에만 적용됩니다. 런타임시 CLR은 항상 참조 어셈블리 버전 번호와 정확히 일치해야합니다. 빌드 타임에 최신 버전을 사용한 경우 런타임시 최신 버전이어야합니다.
Hans Passant

1
VS2013 및 닷넷 4.5.1주의 AutoGenerateBindingRedirects 그들은 특정 버전을 사용하도록했다하더라도 새 버전으로 바인딩 dll을 리디렉션 할 수 있습니다
데니스 Kuypers

1
@HansPassant [AssemblyVersion]어셈블리에 강력한 이름이 서명되지 않은 경우 CLR이 고려하지 않는다고 생각 했습니다.
tm1
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.