우리는 가끔씩 리플랙션을 사용한다.
사용하는 목적 또한 다양하고 리플랙션의 장점 또한 무궁무진 하다.
오늘 이야기할 내용은 어셈블리는 리플랙션을 하는데 있어 무척 도움이 될만한 내용을 살펴보겠다.
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 로 어셈블리를 복사하면서 수행하게 되면 리플랙션을 잘 작동 될 것이다.
그럼 이만 ^^;
'.NET > C#' 카테고리의 다른 글
[제네릭 2편] 제네릭 컬렉션의 사용법 2007-07-01 (0) | 2007.07.01 |
---|---|
[제네릭 1편] 제네릭이란 무엇인가? 새로운 컬렉션의 소개 (0) | 2007.06.30 |
참조된 어셈블리의 Reflection 트러블 슈팅 (0) | 2007.06.02 |
Reflection 을 통한 Event 제어 (0) | 2007.05.17 |
C# 으로 만든 네이버 OpenAPI (0) | 2007.04.05 |
CDO 객체를 이용하여 야후 메일 보내기 (0) | 2007.04.05 |