3. Implementation/C#
How to load an assembly at runtime that is located in a folder that is not the bin folder of the application
SSKK
2012. 2. 17. 06:39
A.dll
B.dll
Common.dll
이 있습니다. Common.dll 은 A, B 모두에게 사용되기 때문에 같이 개발되고 빌드됩니다. 하지만 A.dll 과 B.dll 은 각기 다른 목적을 가지고 있기 때문에 다른 위치에 배포됩니다. 예를 들어
Test1/
이렇게 배포를 했는데 문제가 생겼습니다. Test1, Test2 는 각기 다르게 배포되고 Common.dll 은 여러버전이 존재할 수 있습니다. A 가 처음 로딩될 때는 Test1 의 Common.dll 이 정상적으로 로딩되었으나, 그 다음에 B가 로디오될 때는 Test2 에 있는 Common.dll 이 아니라 이미 로딩되어 있는 Test1/Common.dll 을 그대로 사용하는 문제였습니다. (A.dll 과 B.dll 은 모두 COM 이기 때문에 배포시 'regasm.exe /codebase a.dll" 과 같이 codebase 로 글로벌하게 등록되어 있습니다.)
이 문제를 수정하기 위해 자료를 찾다가 MS 에서 제공하는 아래 링크 정보를 찾았습니다.
http://support.microsoft.com/kb/837908
3가지 방법을 소개 하고 있는데 그중에 3번째인 AssemblyResolve 이벤트라는 재밌는 녀석이 나옵니다.
핸들러 등록 방법
핸들러 코드 예제
주의: 위 코드가 제기된 문제를 해결했다는 건 아닙니다. 아직 적용을 해보지 못했습니다.
B.dll
Common.dll
이 있습니다. Common.dll 은 A, B 모두에게 사용되기 때문에 같이 개발되고 빌드됩니다. 하지만 A.dll 과 B.dll 은 각기 다른 목적을 가지고 있기 때문에 다른 위치에 배포됩니다. 예를 들어
Test1/
A.dll
Common.dll
Common.dll
Test2/
B.dll
Common.dll
Common.dll
이렇게 배포를 했는데 문제가 생겼습니다. Test1, Test2 는 각기 다르게 배포되고 Common.dll 은 여러버전이 존재할 수 있습니다. A 가 처음 로딩될 때는 Test1 의 Common.dll 이 정상적으로 로딩되었으나, 그 다음에 B가 로디오될 때는 Test2 에 있는 Common.dll 이 아니라 이미 로딩되어 있는 Test1/Common.dll 을 그대로 사용하는 문제였습니다. (A.dll 과 B.dll 은 모두 COM 이기 때문에 배포시 'regasm.exe /codebase a.dll" 과 같이 codebase 로 글로벌하게 등록되어 있습니다.)
이 문제를 수정하기 위해 자료를 찾다가 MS 에서 제공하는 아래 링크 정보를 찾았습니다.
http://support.microsoft.com/kb/837908
3가지 방법을 소개 하고 있는데 그중에 3번째인 AssemblyResolve 이벤트라는 재밌는 녀석이 나옵니다.
핸들러 등록 방법
AppDomain currentDomain = AppDomain.CurrentDomain; currentDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler);
핸들러 코드 예제
private Assembly MyResolveEventHandler(object sender,ResolveEventArgs args) { //This handler is called only when the common language runtime tries to bind to the assembly and fails. //Retrieve the list of referenced assemblies in an array of AssemblyName. Assembly MyAssembly,objExecutingAssemblies; string strTempAssmbPath=""; objExecutingAssemblies=Assembly.GetExecutingAssembly(); AssemblyName [] arrReferencedAssmbNames=objExecutingAssemblies.GetReferencedAssemblies(); //Loop through the array of referenced assembly names. foreach(AssemblyName strAssmbName in arrReferencedAssmbNames) { //Check for the assembly names that have raised the "AssemblyResolve" event. if(strAssmbName.FullName.Substring(0, strAssmbName.FullName.IndexOf(","))==args.Name.Substring(0, args.Name.IndexOf(","))) { //Build the path of the assembly from where it has to be loaded. strTempAssmbPath="C:\\Myassemblies\\"+args.Name.Substring(0,args.Name.IndexOf(","))+".dll"; break; } } //Load the assembly from the specified path. MyAssembly = Assembly.LoadFrom(strTempAssmbPath); //Return the loaded assembly. return MyAssembly; }
주의: 위 코드가 제기된 문제를 해결했다는 건 아닙니다. 아직 적용을 해보지 못했습니다.