2008-10-22 3 views
36

저는 클라이언트 시스템 내의 여러 환경 및 지역에 배포 된 .NET 응용 프로그램에 대한 정보를보고하는 도구를 작성하고 있습니다.리플렉션 작업을 위해 .NET 어셈블리를로드 한 다음 언로드하는 방법은 무엇입니까?

이 어셈블리의 어셈블리 특성 값을 읽고 싶습니다.

이 방법은 Assembly.ReflectionOnlyLoad을 사용하여 수행 할 수 있지만이 방법으로도 어셈블리가로드 된 상태로 유지됩니다. 여기서 문제는 다른 경로에서 같은 이름을 가진 두 개의 어셈블리를로드 할 수 없기 때문에 다른 시스템에 배포 된 동일한 응용 프로그램을 자연스럽게 비교할 수 없다는 것입니다.

이 시점에서 해결책은 임시 AppDomain을 사용하는 것으로 가정합니다.

다른 사람이 다른 AppDomain에 어셈블리를로드하는 방법을 자세히 설명하고 속성을 읽고 AppDomain을 언로드 할 수 있습니까?

이것은 URL 주소의 어셈블리뿐만 아니라 파일 시스템의 어셈블리에서도 작동해야합니다. MSDN documentation of System.Reflection.Assembly.ReflectionOnlyLoad (String)에서

답변

47

:

반사 전용 컨텍스트가 다른 상황에서 다른 어떤 없습니다. 컨텍스트에로드 된 어셈블리는 응용 프로그램 도메인을 언로드해야만 언로드 할 수 있습니다.

그래서 어셈블리를 언로드하는 유일한 방법은 응용 프로그램 도메인을 언로드하는 것입니다. 그것으로 새로운 응용 프로그램 도메인 및로드 어셈블리를 만들려면 :

public void TempLoadAssembly() 
{ 
    AppDomain tempDomain = AppDomain.CreateDomain("TemporaryAppDomain"); 
    tempDomain.DoCallBack(LoaderCallback); 
    AppDomain.Unload(tempDomain); 
} 

private void LoaderCallback() 
{ 
    Assembly.ReflectionOnlyLoad("YourAssembly"); 
    // Do your stuff here 
} 
+0

덕분에,이 유용한 패턴처럼 보이는 ReferenceLoader에게 있습니다. –

+1

Assembly.RefrectionOnlyLoad (...)가 현재 도메인에 있지만 TemporaryAppDomain에 어셈블리를로드하지 않습니다? – Anzurio

+3

AZ : 아니요. AppDomain.DoCallback "지정된 대리인으로 식별되는 다른 응용 프로그램 도메인의 코드를 다시 테스트합니다."(MSDN). Assembly의 문서.ReflectionOnlyLoad는 "어셈블리가 호출자의 응용 프로그램 도메인의 리플렉션 전용 컨텍스트에로드됩니다."(다시 MSDN)를 명시합니다. 이는 어셈블리가 실제로 임시 앱 도메인에로드되었음을 의미합니다. –

4

당신은 COM과 쉽게 래퍼의 어떤 종류의 .NET 응용 프로그램에서 사용할 수있는, Unmanaged Metadata API를 사용하려고 할 수 있습니다.

+0

안녕하세요. 이 링크를 가져 주셔서 감사합니다. 곧이 작업을 다시 살펴보고이 API를 확실히 시험해 보겠습니다. 실제로 어셈블리를로드하는 것보다 효율적이라고 기대하고 있습니다. –

3

응용 프로그램 도메인을 사용해야하므로 다른 방법으로 어셈블리를 언로드 할 수 없습니다. 기본적으로이 같은 코드를 사용해야합니다 :

 

AppDomain tempDomain = AppDomain.CreateDomain("Temp Domain"); 
tempDomain.Load(assembly); 
AppDomain.Unload(tempDomain); 

9

정말 당신이 당신이 System.Diagnostics.FileVersionInfo를 사용할 수있는 파일의 버전 번호를 얻으려고 노력하는 경우, 어셈블리를 언로드에 대한 하다니.

public string Comments { get; } 
public string CompanyName { get; } 
public int FileBuildPart { get; } 
public string FileDescription { get; } 
public int FileMajorPart { get; } 
public int FileMinorPart { get; } 
public string FileName { get; } 
public int FilePrivatePart { get; } 
public string FileVersion { get; } 
public string InternalName { get; } 
public bool IsDebug { get; } 
public bool IsPatched { get; } 
public bool IsPreRelease { get; } 
public bool IsPrivateBuild { get; } 
public bool IsSpecialBuild { get; } 
public string Language { get; } 
public string LegalCopyright { get; } 
public string LegalTrademarks { get; } 
public string OriginalFilename { get; } 
public string PrivateBuild { get; } 
public int ProductBuildPart { get; } 
public int ProductMajorPart { get; } 
public int ProductMinorPart { get; } 
public string ProductName { get; } 
public int ProductPrivatePart { get; } 
public string ProductVersion { get; } 
public string SpecialBuild { get; } 
1

당신은 새로운 응용 프로그램 도메인의 인스턴스를 만들고 해당 인스턴스에서 코드를 실행할 수 있습니다

var info = FileVersionInfo.GetVersionInfo(path); 

FileVersionInfo에는 다음과 같은 속성이 있습니다.

var settings = new AppDomainSetup 
{ 
    ApplicationBase = AppDomain.CurrentDomain.BaseDirectory, 
}; 
var childDomain = AppDomain.CreateDomain(Guid.NewGuid().ToString(), null, settings); 

var handle = Activator.CreateInstance(childDomain, 
      typeof(ReferenceLoader).Assembly.FullName, 
      typeof(ReferenceLoader).FullName, 
      false, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, null, null, CultureInfo.CurrentCulture, new object[0]); 


var loader = (ReferenceLoader)handle.Unwrap(); 

//This operation is executed in the new AppDomain 
var paths = loader.LoadReferences(assemblyPath); 


AppDomain.Unload(childDomain); 

여기

public class ReferenceLoader : MarshalByRefObject 
{ 
    public string[] LoadReferences(string assemblyPath) 
    { 
     var assembly = Assembly.ReflectionOnlyLoadFrom(assemblyPath); 
     var paths = assembly.GetReferencedAssemblies().Select(x => x.FullName).ToArray(); 
     return paths; 
    } 
} 
+0

완벽한 - 다음과 같이 LINQPad에서 실행하는 하나의 작은 변화했습니다 : 'VAR 설정 = 새 AppDomainSetup { \t \t ApplicationBase = Path.GetDirectoryName (this.GetType() Assembly.Location.) \t을};' –

관련 문제