2010-05-16 5 views
3

이 항목은 실제로 나를 화나게합니다. 여기에 간다 :aspx 페이지의 동적 어셈블리를 컴파일하는 동안 AssemblyResolve 이벤트가 발생하지 않습니다.

내 목표는 포함 된 aspx, ascx 등이 포함 된 런타임에 어셈블리를로드하는 것이다. 응용 프로그램을 다시 시작하려면 (이전 버전이로드 된 채로 남아 있음을 알고 있습니다.)

그 목적을 위해 나는 트릭을 수행하는 가상 경로 공급자를 작성했습니다. 프레임 워크를 내 어셈블리로 리디렉션 할 수 있도록 CurrentDomain.AssemblyResolve 이벤트를 구독했습니다.

문제는이 프레임 워크는 내가 다음 얻을 영문 페이지에 대한 동적 어셈블리를 컴파일하려고 할 때 :

컴파일러 오류 메시지 : CS0400 : 형식 또는 네임 스페이스 이름 '페이지가'에서 찾을 수 없습니다 글로벌 네임 스페이스 (당신은 어셈블리 참조가없는?)

소스 오류 : 공용 클래스 app_resource_pages__version_1_0_0_0__culture_neutral__publickeytoken_null_default_aspx : 글로벌 :: Pages._Default, System.Web.SessionState.IRequiresSessionState, System.Web.IHttpHandle

Assembly.Load (AssemblyName) 또는 Assembly.LoadFrom (filename)을 사용하여 어셈블리를로드하면 위의 오류가 발생합니다. Assembly.Load (byte [])로로드하면 (잠그지 않도록) 예외가 throw되지만 AssemblyResolve 핸들러가 호출되면 어셈블리가 제대로 반환됩니다 (한번 호출 됨).

그래서 프레임 워크가 asp 태그를 구문 분석 할 때 한 번 호출되지만 aspx 페이지에 대한 동적 어셈블리를 만들려고 시도하지 않을 것으로 추측합니다.

+0

실제 질문은 여기에 무엇입니까? 비 잠금, 비 차단 방식으로 새로운 .aspx 페이지를로드하는 방법? lede 묻혀 보인다. –

+0

질문은 aspx 페이지를 컴파일하는 동안 AssemblyResolve 이벤트가 실행되지 않는 이유입니다. 해결 방법이 있습니까? – John

답변

4

누락 된 어셈블리 참조의 원인은 확실하지 않지만 조금 뒤로 물러나 프로그램이 예상대로 작동하면 다른 문제를 해결해야합니다. 이 문제는로드 된 어셈블리의 잠금입니다. .Net 프레임 워크는 항상로드 된 어셈블리를 잠급니다. bin 폴더에서 dll 파일을 업데이트 할 수있는 이유는 실제로 트릭입니다. 자, AppDomain에는 ShadowCopyDirectories이라는 멋진 속성이 있습니다.이 속성은 어셈블리를로드 할 때 섀도 복사본이 될 디렉터리를 지정합니다.

public Assembly GetAssembly() 
    { 
     Assembly result = cache.Get(assemblyKey) as Assembly; 

     if (result == null) 
     { 
      lock (this) 
      { 
       result = cache.Get(assemblyKey) as Assembly; 
       if (result == null) 
       { 
        assemblyName = System.Reflection.AssemblyName.GetAssemblyName(assemblyFile); 
        result = Assembly.Load(assemblyName); 
        cache.Add(assemblyKey, result, new CacheDependency(assemblyFile), Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.High, new CacheItemRemovedCallback(OnAssemblyRemoved)); 
       } 
      } 
     } 
     return result; 
    } 

이 단지 작품을 할 때 새 어셈블리 : 나는 그것을 다음과 같은 작업을 얻었다 고 생각

protected const string ApplicationAssembliesFolder = "~/Assemblies"; 

    protected void Application_Start(object sender, EventArgs e) 
    { 
     var assembliesPath = Server.MapPath(ApplicationAssembliesFolder); 

     AppDomain.CurrentDomain.SetShadowCopyPath(
      AppDomain.CurrentDomain.SetupInformation.ShadowCopyDirectories + 
      Path.PathSeparator + assembliesPath); 

     Assembly.LoadFrom(
      Path.Combine(assembliesPath, "Example.dll")); 
    } 
+0

그래, shadowcopypath를 설정하면 프레임 워크가 디스크에서 파일을 잠그지 못하지만 ... Assembly.LoadFrom에 대한 후속 호출 (파일이 더 이상 디스크에없는 경우에도 동일한 어셈블리 반환 oO – John

1

: 그래서 그림자 복사 된 디렉토리 목록을 변경하여 당신은 당신의 어셈블리를 잠그지 않고 임의의 폴더에서로드 할 수 있습니다 종류가 다른 오래된 버전과 다른 버전이 있습니다. 응용 프로그램이 다시 시작되지 않지만 새 어셈블리가로드됩니다. aspx 페이지의 마크 업과 코드 숨김을 모두 업데이트하려고 시도했지만 예상대로 작동했습니다.

은 요약하면 :

  1. AppDomain.CurrentDomain.SetShadowCopyPath
  2. Assembly.Load (AssemblyName.GetAssemblyName (assemblyFile))
관련 문제