2012-01-02 1 views
3

제 3 자 라이브러리를 참조하는 프로젝트가 있습니다. 라이브러리 제조업체는 정기적으로 새 버전을 출시합니다. 내 궁극적 인 목표는 런타임에 실행 중에 사용해야하는 런타임을 선택할 수있게하는 것입니다.런타임에 강력하게 서명 된 어셈블리 교환

지금은 컴파일 할 때 사용한 버전보다 높은 버전 번호의 런타임에 어셈블리를로드하려고합니다. 내 프로젝트를 컴파일하고 제 3 자 라이브러리를 최신 버전으로 바꾸고 응용 프로그램을 실행 해 봅니다. 이것은 내가 문제가되었다는 것입니다.

나는이 오류를 볼 supprised하지 않았다

는 "위치 어셈블리의 매니페스트 정의가 어셈블리 참조와 일치하지 않습니다", 어셈블리가 강력하게 체결되어 있기 때문에 : 나는 오류가 말을 얻을. 나는 이것을 우회하는 방법을 찾았지만 지금까지 아무런 운이 없었습니다.

바인딩 리디렉션이 나를 도울 수 있다고 생각했지만 다양한 "새 버전"을 지정할 수 없다는 단점이 있습니다. 모든 조합이 작동해야하며 이전 버전은 최신 버전으로, 그 반대의 경우도 마찬가지입니다.

http://msdn.microsoft.com/en-us/library/eftw1fys.aspx

<bindingRedirect oldVersion="1.2.7.0" newVersion="1.2.8.0" /> 

는 또한 동적 호출을 검토 한 결과, 그러나 나는 (내 코드가 광범위하게 제 3 회 파티 어셈블리에 정의 된 형식을 사용) 형태의 안전성을 풀어. -> 참조를 제거하는 것이 어렵습니다.

프로젝트 정의의 참조에서 공개 키를 제거하지 못했습니다. 다른 모든 어셈블리 버전과 컴파일하는 동안 사용 된 버전이 실패합니다.

<Reference Include="<assemblyname>"> 
    <SpecificVersion>False</SpecificVersion> 
    <HintPath>..\..\Dependencies\<manufacturer>\1.2.7.0\<assemblyname>.dll</HintPath> 
</Reference> 

참고 : 논리로드하고 이미 실행시 어셈블리를 언로드합니다. 타사 라이브러리에 사용할 수있는 인터페이스가 없습니다.

+2

Brr이 기능은 DLL 지옥을 요구합니다. 강력한 이름 지정과 아무런 관련이 없지만 [AssemblyVersion]의 불일치로 인해 예외가 발생합니다. 실제로 bindingRedirect 만 좋은 해결책입니다. 벤더가 호환 가능한 어셈블리에 대해 [AssemblyFileVersion] 만 증가시키지 않으면 설득력이 없습니다. [AssemblyVersion]을 증가시키지 않으면 "호환되지 않음, 시도하지 않음"을 의미합니다. –

+0

@HansPassant AssemblyVersion이 실제로 증분되어 매니페스트 불일치가 발생합니다. 매니페스트 불일치가 강하게 서명 된 어셈블리에서만 발생할 수 있다고 말하는 것이 맞습니까? 또는 문제가 서명되지 않은 어셈블리에도 적용됩니까? [어셈블리 버전] (http://msdn.microsoft.com/en-us/library/51ket42z.aspx) – Nickolas

+0

아니요, [AssemblyVersion] 만 중요합니다. 서명되지 않은 어셈블리에서도 똑같은 방식으로 실패합니다. –

답변

1

AppDomain에서 AssemblyResolve 이벤트를 처리하면이 문제를 쉽게 해결할 수 있습니다 (해결 방법이 더 적절할 수 있습니다). 이 이벤트를 처리하면 어셈블리를 찾는 모든 일반적인 방법으로 일치하는 버전을 찾지 못한 경우로드해야하는 어셈블리를 코드에 제공 할 수 있습니다.

ResolveEventArgs.Name 속성을 검사하여로드해야하는 어셈블리인지 확인해야합니다. Name 속성은로드되는 어셈블리의 긴 이름입니다 (예 : 'Widget.Net, Version = 1.2.3.4, Culture = neutral, PublicKeyToken = xxxxxxxxxxx').

정확한로드 요청이 확인되면 올바른 버전의 어셈블리 (Assembly.LoadFrom, Assembly.Load, Assembly.LoadWithPartialName)를로드하고 이벤트 처리기에서 반환하십시오. Assembly.LoadWithPartialName은 쓸모없는 것으로 표시되지만 대상 어셈블리가 GAC에있는 경우이 문제를 처리하는 유일한 방법 인 것처럼 보입니다.

문제를 '해결하는'동안 어떤 의미에서는 좋은 해결책이 아니라는 점을 알아 두는 것이 중요합니다. .Net 프레임 워크에서 사용하는 어셈블리에 대한 일반 버전 및 강력한 이름 확인을 완전히 뒤집습니다. 다른 옵션이 없을 때 당신이하는 일은 벤더가 그들의 어셈블리를 버전 관리하는 것을 엉망으로 만들었 기 때문입니다. 또한 참조 된 버전과로드 된 버전 사이에 어셈블리에 정의 된 클래스에 대한 중요한 변경이 필요하지 않습니다. 즉, 사용하는 모든 클래스, 속성 및 메서드 등이 여전히 존재하며 동일한 서명을 가지고 있어야합니다.

보안의 적어도 구실을 유지하려면, 그것은 아주 좋은 생각이 될 것이라고 AssemblyResolve 이벤트 처리기에서 적어도 확인하려면 다음

  1. 로드 된 어셈블리 버전은 버전이
  2. 요청보다 새로운 로드되고 요청 된 어셈블리의 공용 키 토큰은 일치합니다.
관련 문제