2009-07-27 4 views
6

나는 지난 두 주 동안이 문제를 해결하려고했지만 아직 좋은 해결책을 찾지 못했습니다. 잘하면 여기에 답을 얻을 수 있습니다.런타임에 두 가지 버전의 어셈블리를로드 중

공통 프로젝트/DLL (ZC)을 가리키고 있지만 다른 버전에있을 수있는 두 어셈블리 (ZA & ZB)가 있습니다 (동일한 DLL 이름, 동일한 네임 스페이스, 일부 클래스가 다를 수 있음) . 그러나 각 어셈블리는 자체적으로 작동하지만 런타임에 다른 어셈블리에로드되는 경우 (예 : A로드 B) 작업을 수행 할 수 없습니다. 도움이 필요해. 여기

는 설정이다 : ZB는 ZC 버전에 따라 1.1
  • ZA는 ZB에서 뭔가를로드 할 필요를로드해야 1.0

  • (

    • ZA는 ZC에 따라 (공통) 버전있는 런타임에 ZC에 따라 다름).

      ZA가 마스터 앱입니다. bin 디렉토리 아래에는 ZB와 그 의존성 (ZC)을 모두 배치하고자하는 플러그인 디렉토리 plugins/plugin-ZB이 있습니다.

      는 여기에 지금까지 시도한 작업은 다음과 같습니다

      Assembly.Load() DLL의 동일한 버전을 사용 - 일했다 괜찮.

      Assembly.Load() 다른 버전의 dll - ZB로드를 사용하지만 메소드가 실행될 때 메소드를 찾을 수없는 예외가 발생합니다.

      AppDomain.Load() 파일을 찾을 수 없습니다 오류가 발생했습니다. 심지어 대표자를 사용하여 어셈블리를 해결했습니다.

      ZC에 관한 세부 정보 : - 일부 방법은 공개 정적입니다 (일부는 그렇지 않습니다). 예 : Log.Log("hello"); - 일부는 값 (프리미티브 또는 객체)을 반환 할 수 있습니다. - 일부 메서드는 비 정적 (및 반환 값)입니다.

      도움 말? - TIA

    답변

    1

    조나단 알렌의 훌륭한 충고 외에도 두 가지 버전의 AppDomanis에 두 가지 버전을로드하면 문제를 해결할 수있는 "고전적인"방법이 있습니다. 그런 다음 .NET Remoting을 사용하여 두 AppDomains를 comunicate로 만들 수 있습니다. 그래서 ZA는 AppDomain ZB에서 새로운 Appdomain, Load를 생성하고 Remoting을 통해 ZB에서 일부 작업을 호출해야합니다.

    .NET Remoting에는 사용할 클래스에 대한 몇 가지 요구 사항 (MarshalByRef의 상속)이 있으며 AppDomain을 만드는 것은 비용이 많이 드는 작업입니다.

    희망 도움말

    +0

    는 "당신 만의 AppDomain에 대한 어셈블리의 한 버전을 가질 수 있습니다"사실이 아니다. 하나의 어셈블리에서 두 버전의 어셈블리를 참조 할 수도 있습니다. 자세한 내용은 extern 별칭을 참조하십시오.이 예제는 Google에서 기능의 예와 함께 가장 먼저 나타납니다. http://blogs.msdn.com/ b/ansonh/archive/2006/09/28/extern-alias-walkthrough.aspx – Graham

    +0

    두 AppDomains를 사용하면 설명 된 문제에 대한 해결책입니다. – Graham

    +0

    맞아요, 대답이 업데이트되었습니다! –

    0

    동일한 어셈블리의 두 가지 버전이 동시에로드되었습니다. 당신이 설명하는 것처럼 시나리오가 발생했습니다.

    ZA 및 ZB 모두에 대해 동일한 버전의 ZC를로드하도록 런타임에 확신시켜야합니다.

    1. 당신의 app.config 파일에 bindingRedirect 요소를 사용 : 그 두 가지 방법을 발견했다. this question에는 몇 가지 세부 정보가 있습니다.
    2. AppDomain.AssemblyResolve 이벤트를 사용하십시오. this answer에는 몇 가지 세부 정보가 있습니다.

    AppDomain.AssemblyResolve의 유일한 문제점은 런타임에서 요청 된 버전을 찾을 수없는 경우에만 트리거된다는 것입니다. 두 버전을 모두 사용할 수있는 경우 bindingRedirect을 사용해야합니다. AppDomain.AssemblyResolve 이벤트를 사용한 다음 어셈블리의 참조 된 어셈블리 컬렉션을 조사하여 올바른 버전이로드되었는지 확인하는 안전성 검사를 추가했습니다. 그렇지 않은 경우 사용자에게 라이브러리의 이전 버전이 거짓말을하고 그것이 어디에 있는지 알려주고 있습니다.

    +1

    두 가지 다른 버전을로드하지 않고 동일한 버전을 두 번로드합니다. –

    +1

    이 문제가 생겼을 때 @Cameron, ZA가 시작될 때 실행 시간에 ZC 버전 1.1이로드되었습니다. 그런 다음 ZB 플러그를로드하면 실행 시간에 버전 1.0의 ZC가로드됩니다. 두 가지 버전을로드하면됩니다. ZA와 ZB가 ZC에서 서로 객체를 전달하도록하기 위해 두 객체 모두 동일한 버전의 ZC를로드해야했습니다. 그게 내가 대답하는 방법을 설명하는거야. 나는 원래 질문을 오해 했는가? –

    3
    m_Assembly1 = Reflection.Assembly.LoadFile(IO.Path.Combine(System.Environment.CurrentDirectory, "Old Version\Some.dll")) 
        m_Assembly2 = Reflection.Assembly.LoadFile(IO.Path.Combine(System.Environment.CurrentDirectory, "New Version\Some.dll")) 
    
        Console.WriteLine("Old Version: " & m_Assembly1.GetName.Version.ToString) 
        Console.WriteLine("New Version: " & m_Assembly2.GetName.Version.ToString) 
    
        m_OldObject = m_Assembly1.CreateInstance("FullClassName") 
        m_NewObject = m_Assembly2.CreateInstance("FullClassName") 
    

    여기에서 후기 바인딩 및/또는 반사를 사용하여 테스트를 실행했습니다.

    .NET: Load two version of the same DLL

    +0

    훌륭한 조언! 몰랐다. –

    관련 문제