블로그 이미지
Kanais
Researcher & Developer 퍼즐을 완성하려면 퍼즐 조각들을 하나 둘씩 맞춰나가야 한다. 인생의 퍼즐 조각들을 하나 둘씩 맞춰나가다 보면 인생이란 퍼즐도 완성되는 날이 오려나...?

calendar

1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

Notice

05-02 09:56

Recent Post

Recent Comment

Recent Trackback

Archive

2015. 5. 19. 16:41 Programming/.NET

 

작성날짜    : 2011-04-15


출처 : 선문 비트 프로젝트 http://cafe.daum.net/smbitpro

참고 사이트 : http://msdn.microsoft.com/ko-kr/library/ms173183.aspx

 

Reflection(C#)

리플렉션은 런타임에 어셈블리, 모듈 및 형식을 캡슐화하는 개체를 제공받아 이를 사용하는 것을 말합니다.

리플렉션을 통해 어셈블리에 정의된 형식을 조사하거나 모듈에 정의된 형식을 조사 할  수 있습니다.

그리고, 런타임에 특정 어셈블리를 로딩하여 해당 어셈블리내의 형식의 인스턴스를 생성 및 형식 내 멤버를 사용할 수도 있습니다.

리플렉션의 루트 클래스인 System.Type클래스를 통해 NET 메타 데이터를 얻을 수 잇으며 Object클래스에 GetType메서드를 노출하고 있기 때문에 모든 개체의 GetType메서드를 이용을 할 수 있습니다.

 

개발도구를 통해 리플렉션에 대해 살펴보기로 합시다.  프로젝트 명은 AboutReflection으로 하겠습니다.

먼저, 예를 들기 위해 간단한 클래스를 하나 정의하겠습니다.

class Example

    {

        int num;

        string name;

        public int Num

        {

            get

            {

                return num;

            }

        }

        public Example(int _num, string _name)

        {

            num = _num;

            name = _name;

        }

        public override string ToString()

        {

            return String.Format("번호 : {0} 이름 : {1}", num, name);

        }

        public void Study()

        {

            Console.WriteLine(ToString() + "공부 중...");

        }

    }

-    num name필드가 있고 num필드에 접근하기 위한 속성 Num이 있습니다.

-    그리고, 번호와 이름을 입력 인자로 받는 생성자와 재정의된 ToString메서드와Study라는 메서드가 있습니다.

 

먼저 Example클래스 개체를 가지고 리플렉션에 대해 살펴봅시다.

먼저 Example 개체를 생성하고 해당 개체의 GetType메서드를 통해 Type 개체를 얻어오겠습니다.

 

Example ex = new Example(3"홍길동");

 

Type클래스 개체에는 형식 메터데이터에 액세스를 하기 위한 주요 클래스 입니다.

GetType메서드는 Object클래스에 public으로 노출된 메서드 입니다.

            

Type type = ex.GetType();

 

Type개체를 통해 내부 멤버들을 조사할 수도 있습니다.  GetMembers메서드를 통해 MemberInfo배열을 반환을 받게 되는데 이를 통해 어떠한 멤버가 있는지 확인해 봅시다.

MemberInfo[] minfos = type.GetMembers();

    Console.WriteLine("Example의 멤버들");

    foreach (MemberInfo minfo in minfos)

    {

         Console.WriteLine("\t" + minfo.ToString());

    }

 


실행해서 보면 알 수 있듯이 노출된 모든 멤버들을 확인할 수가 있습니다.

 

그 외에도 Type을 통해 메서들들이나 필드, 속성등 원하는 것들을 조사할 수 있습니다.

이번에는 메서드들을 얻어와 봅시다.  GetMethods메서드를 통해 MethodInfo 배열을 얻어와서 확인할 수 있습니다.

            

MethodInfo[] methodinfos = type.GetMethods();

    Console.WriteLine("\n\nExample의 메서드들");

    foreach (MethodInfo mi in methodinfos)

    {

         Console.WriteLine("\t" + mi.ToString());

    }

 


실행해 보면 기대되는 동작을 수행할 것입니다.

 

그리고, 단순히 조사 뿐만이 아니고 반영을 할 수도 있습니다.  이번에는 Study메서드 정보를 얻어와서 MethodInfo의 Invoke메서드를 호출해 볼께요.  첫 번째 인자는 개체 인스턴스를 넣고 그 이후에는 입력 매개변수들을 넣으면 됩니다.

            

Console.WriteLine("\n\n");

    MethodInfo mi2 = type.GetMethod("Study");

    mi2.Invoke(ex, null);

 


실행해 보니 앞에서 생성한 ex개체의 Study메서드가 호출됨을 알 수 있죠.

 

이와 같이 Type을 통해 런 타임시에 형식에 대한 정보를 얻어오고 반영할 수 있습니다.

 

이외에도 리플렉션은 동적으로 어셈블리를 로딩하여 해당 어셈블리 내의 형식을 얻어오고 이를 사용할 수도 있습니다.

 

이에 대해 간단히 살펴보기로 합시다.

 

먼저 ClassLibrary 프로젝트를 하나 만듭시다.  프로젝트 명은 DemoLibrary라 할께요.

 

그리고, 간단히 Stu 클래스를 정의하겠습니다.

class Stu

    {

        int num;

        string name;

        public int Num

        {

            get

            {

                return num;

            }

        }

        public Stu(int _num, string _name)

        {

            num = _num;

            name = _name;

        }

        public override string ToString()

        {

            return String.Format("번호 : {0} 이름 : {1}", num, name);

        }

        public void Study()

        {

            Console.WriteLine(ToString() + "공부 중...");

        }

    }

 

Example클래스 처럼 num,name필드와 Num속성, 생성자,ToString에 대한 재 정의, Study메서드로 구성하였습니다.

         

컴파일을 하시고 해당 dll을 리플렉션 프로젝트 출력 디렉토리로 복사를 할께요.

 

위쪽은 주석 처리 하고요.

 

먼저, DemoLibrary를 동적으로 로딩을 먼저 할께요.

Assembly클래스의 정적 메서드인 Load를 통해 어셈블리를 로딩할 수 있습니다.  공용 어셈블리의 경우에는 강력한 이름을 사용해야 하니 주의하시기 바랍니다.

        

Assembly asm = Assembly.Load("DemoLibrary");

    

먼저, 동적 로딩한 어셈블리에 어떠한 형식들이 있는지 알아 봅시다.  Assembly 개체에 GetType메서드를 통해 해당 어셈블리에 있는 형식들에 대한 정보를 얻어올 수 있습니다.

            

Type[] types = asm.GetTypes();

    Console.WriteLine("DemoLibrary내의 형식들");

    foreach (Type type in types)

  {

        Console.WriteLine("\t" + type.ToString());

    }

 

현재 DemoLibrary에는 Demo네임 스페이스에 Stu형식만 있는 것을 알 수 있죠.

 

 그리고, 형식명을 통해서 Type 개체를 얻어올 수도 있으며 앞의 예처럼 Type 개체의 GetMethods메서드를 통해 메서드들에 대한 정보를 얻어올 수도 있습니다.

Type type2 = asm.GetType("DemoLibrary.Stu");

    MethodInfo[] methods = type2.GetMethods();

    Console.WriteLine("DemoLibrary.Stu의 메서드들");

    foreach (MethodInfo mi in methods)

    {

         Console.WriteLine("\t" + mi.ToString());

    }

 

이번에는 개체를 생성하고 메서드를 호출하는 예를 살펴봅시다.

개체를 생성하기 위해서는 Activator클래스의 정적 메서드인 CreateInstance메서드를 사용하시면 됩니다.  첫번째 인자로 생성하고자 하는 형식에 대한 Type개체를 넣어주시고, 그 뒤로 생성자의 입력 인자를 넣어 주시면 됩니다.  Demo의 Stu클래스의 생성자는 번호와 이름을 입력 인자로 받게 구현했었죠.

            

Object obj = Activator.CreateInstance(type2, 2"홍길동");

 

그리고, Type개체의 GetMethod를 통해 호출하고자 하는 메서드 정보를 얻어옵니다.

            

MethodInfo mi2 = type2.GetMethod("Study");

 

마지막으로 위의 예처럼 MethodInfo개체의 Invoke를 호출해 주시면 되는데 Activator의 정적 메서드인 CreateInstance로 생성한 Object를 첫번째 인자로 넣고 그 뒤에 해당 메서드의 입력 매개변수들을 넣으시면 됩니다.

Study메서드는 입력 매개변수가 없으니 null을 주시면 되겠죠.

 

            

mi2.Invoke(obj, null);

  

실행해 보면 잘 동작한다는 사실을 알 수 있습니다.

이와 같은 동적으로 어셈블리를 로딩을 하는 것은 미디어 플레이어와 같이 응용 프로그램과 사용하는 어셈블리의 배포가 별도로 이루어 지는 경우나 .NET 리모팅에서 제네릭 어셈블리에서 코어 어셈블리를 동적으로 로딩하여 사용하는 등 .NET 고급 기술에서 사용될 수 있다는 것을 기억해 두시기 바랍니다.



'Programming > .NET' 카테고리의 다른 글

[.NET] Delegate (대리자) - 2  (0) 2015.05.19
[.NET] DataRepeater Control  (0) 2015.05.19
[.NET] DataAdapter 생성  (0) 2015.05.19
[.NET] DataAdapter  (0) 2015.05.19
[.NET] try-catch-finally  (0) 2015.05.19
posted by Kanais