우리는 가끔씩 리플랙션을 사용한다.
사용하는 목적 또한 다양하고 리플랙션의 장점 또한 무궁무진 하다.
 
오늘 이야기할 내용은 어셈블리는 리플랙션을 하는데 있어 무척 도움이 될만한 내용을 살펴보겠다.
 
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.IO;
 
namespace ConsoleTest1
{
       class Program
       {
             static void Main(string[] args)
             {
                    try
                    {
                           BindingFlags flag = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;
                           // 실행중인 응용프로그램의 경로를 표시한다.
                           Console.WriteLine(Environment.CurrentDirectory);
 
                           // 빌드된 웹페이지의 dll 을 로드한다.
                           Assembly asm = Assembly.LoadFrom(@"C:\Documents and Settings\Administrator\My Documents\Visual Studio 2005\Projects\UmcTest\ConsoleTest1\bin\Debug\App_Web_articlecontrol.ascx.51af1afc.dll");
 
                           // 모듈을 로드한다.
                           foreach (Module module in asm.GetModules())
                           {
                                 // 모듈 이름 출력
                                 Console.WriteLine(module.Name);
 
                                 // 클래스의 Type 을 가져온다.
                                 Type type = asm.GetType("WebAdmin_05Article_Controls_ArticleControl");
                           }       
                    }
                    catch (Exception ex)
                    {
                           Console.WriteLine( ex.Message );
                    }
             }
       }
}
 
 
우선 위와 같은 간단한 리플랙션 소스를 놓고 차근차근 살펴보겠다.
 
위 소스는 실행결과 아무런 예외도 내뱉지 않는다.
 
 
어셈블리에 위와 같은 WebAdmin_05Article_Controls_ArticleControl 타입은 분명 존재한다. 그래서 에러가 나지 않는 것일까?
 
결론부터 말하면 절대 아니다.
참고로 위 App_Web_articlecontrol.ascx.51af1afc.dll 어셈블리는 Umc.Core.Dll 을 참조하고 있으며, Umc.Core.Dll 이 있어야 정상적으로 작동할 수 있다.
 
App_Web_articlecontrol.ascx.51af1afc.dll 어셈블리와 Umc.Core.Dll 은 같은 폴더에 놓이게 되면 닷넷 어셈블리는 자동으로 App_Web_articlecontrol.ascx.51af1afc.dll이 로드될 때 Umc.Core.Dll 어셈블리를 참조하게 된다.
 
그럼 좀더 예외상황을 자세히 보도록 하기 위해 다음의 구문에 인자값을 추가해 주자.
 
// 클래스의 Type 을 가져온다.
Type type = asm.GetType("WebAdmin_05Article_Controls_ArticleControl", true, false);
 
위와같이 수정되었으니 다시 한번 실행해 보겠다.
 
 
보시다시피 뭐라뭐라 Exception 메시지가 떠 버렸다.
 
위에서 설명한대로 참조한 어셈블리(Umc.Core.Dll) 이 존재하지 않기에 어셈블리를 정상적으로 로드하지 못한 결과다.
 
만약, 하나의 응용프로그램에 참조된 어셈블리는 한 두개가 아닌, 수개 내지 수십개라고 가정해 볼 때 리플랙션을 수행하는 개발자 입장에선 곤욕이 따로 없을 것이다.
 
그럼 이와 같은 예외가 발생할 때 어떻게 참조된 어셈블리는 알아낼 수 있는지 알아보자.
 
그러기 위해 약간의 소스를 변경해 보겠다.
                                    …
                                    …
                                    …
                           // 모듈을 로드한다.
                           foreach (Module module in asm.GetModules())
                           {
                                 // 모듈 이름 출력
                                 Console.WriteLine("Module Name : " + module.Name);
 
                                 // 클래스의 Type 을 가져온다.
                                 Type[] type = asm.GetTypes();
                           }
                    }
                    catch (ReflectionTypeLoadException ex)
                    {
                           Console.WriteLine( ex.Message );
                    }
 
단순히 어셈블리의 모듈별로 Types 를 가져오도록 했다.
 
 
위에서 말한대로 참조된 어셈블리를 로드할 수 없어 ReflectionTypeLoadException이 떠버렸다.
 
그럼 참조하지 못한 수개 또는 수십개의 어셈블리를 나열해 보자.
 
다음과 같이 소스를 수정해 보기 바란다.
 
catch (ReflectionTypeLoadException ex)
{
       Console.WriteLine("-----------------------------------------------------------");
       foreach (Exception ex1 in ex.LoaderExceptions)
       {
             FileNotFoundException fex = ex1 as FileNotFoundException;
             if (fex != null)
             {
                    Console.WriteLine(fex.FileName);
             }
       }
}
 
 
하하하.. 결과는 대만족이다.
만약 여러 서드파티 제품 등의 어셈블리, 또는 기타 어셈블를 참조할 경우 참조하지 못한 어셈블리들의 리스트가 쭈욱 뜬다.
 
위와같이 참조하지 못한 어셈블리에 대해 재귀호출을 통하여Environment.CurrentDirectory 로 어셈블리를 복사하면서 수행하게 되면 리플랙션을 잘 작동 될 것이다.
 
그럼 이만 ^^;
Posted by POWERUMC
TAG ,

댓글을 달아 주세요