System.Reflection 네임스페이스의 클래스와 System.Type을 사용하면 로드된 어셈블리와 이 어셈블리에 정의된 클래스, 인터페이스, 값 형식 등의 형식에 대한 정보를 얻을 수 있습니다.

리플렉션을 사용하여 런타임에 형식 인스턴스를 만든 다음, 이 형식 인스턴스를 호출하고 액세스할 수도 있습니다.

 

먼저 System.Type 클래스에 대해서 알아 보겠습니다.

System.Reflection 네임스페이스에 정의되어 있는 많은 항목들이 추상 클래스인 System.Type클래스를 사용하고 있습니다.

System.Type클래스의 대략적인 맴버를 정리 해보겠습니다.

IsAbstract

이 속성들을 이용하면 참조하고 있는 Type에 대한 여러 가지 기본적인 정보를 알아낼 수 있다

IsArray

IsClass

IsCOMObject

IsEnum

IsInterFace

IsPrimitive

IsNestedPublic

IsNestedPrivate

IsSealed

IsValueType

GetConstructors()

이 메소드들을 이용하면 알아내고 싶은 항목들을 나타내는 배열을 얻을 수 있습니다.

GetEvents()

GetFields()

GetInterfaces()

GetMembers()

GetNestedTypes()

GetProperties()

FindMembers()

검색 기준에 기반해서, MemberInfo형식을 배열을 반환한다.

GetType()

이 정적 메소드는 해당 문자열 이름에 대한 Type인스턴스를 반환한다.

InvokeMember()

이 메소드를 이용하면 해당 아이템에서 late바인딩을 이용할 수 있다.

 

System.Type에 대해서 좀더 자세히 알고 싶으시면 아래 주소를 참조해주세요

http://msdn.microsoft.com/ko-kr/library/system.type.aspx

 

다음으로 System.Reflection 네임스페이스에 대해서 알아 보도록 하겠습니다.

 

System.Reflection 네임스페이스의 멤버

Assembly

이 클래서에는 어셈블리를 로드하고 조사하고 조작하하는 데 이용할 수 있는 여러 개의 메소드들이 포함되어 있다.

AssemblyName

이 클래스를 이용하면 어셈블리 자체에 대한 여러가지 상세한 정보를 알아낼 수 있다.

EventInfo

해당 이벤트에 대한 정보를 가진다.

FieldInfo

해당 필드에 대한 정보를 가진다.

MemberInfo

이것은EventInfo, FieldInfo, MethodInfo,

PropertyInfo 형식에 대한 공통의 조작을 정의하는 추상 기본 클래스 이다.

MethodInfo

해당 메소드에 대한 정보를 포함한다.

Module

다중 파일 어셈블리에 있는 해당 모듈에 접근하는 데 이용할 수 있다.

ParameterInfo

해당 매개변수에 대한 정보를 가진다.

PropertInfo

해당 속성에 대한 정보를 가진다.

 

System.Reflection 네임스페이스에 대해서 좀더 자세히 알고 싶으시면 아래 주소를 참조해주세요

http://msdn.microsoft.com/ko-kr/library/system.reflection.aspx

 

아래의 클래스를 Dll로 만들었습니다.

HelloLib.Dll

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace HelloLib

{

    public delegate void MyDele(int a);

    class ExampleClass

    {

        public  event MyDele del=null;

        public int num;

        public string name=string.Empty;

        Dictionary<intstring> dic = new Dictionary<intstring>();

    

        public int Num

        {

            get

            {

                return num;

            }

            set

            {

                num = value;

            }

        }

        public ExampleClass()

        {

           

        }       

        public void Foo()

        {

 

            if (del != null)

            {

                del(4);

            }

            else

            {

                Console.WriteLine("이벤트 핸들러가 연결 안 됨");

            }

        }

        public int Soo(int a, int b)

        {

            return a + b;

        }

        public static int Koo(int a, int b)

        {

            return a * b;

        }

        public string this[int key]

        {

            get

            {

                if (dic.ContainsKey(key))

                {

                    return dic[key].ToString();

                }

                return string.Empty;               

            }

            set

            {

                dic[key] = value;

            }

        }

    }

}

 

 


Dll을 사용하는 방법들은 많습니다.

여태까지는 Dll을 만들면 아래 그림과 같은 참조추가를 하였습니다.



하지만 리플렉션은 컴파일시에 Dll을 참조하는 것이 아니라 런타임시에 Dll의 형식을 알아와 해당 정보에 맞게 사용할 수 있게해줍니다.

 

아래 코드를 통해서 리플렉션에 대해서 알아 보도록 하겠습니다.

1.어셈블리 로딩

사용할 Dll을 지정해 줍니다.

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

 

2. 특정 형식의 리플렉션된 type개체 생성

해당Dll의 네임스페이스 안에 사용할 클래스를 지정해서

그 클래스 형식의 정보를 가지는 type개체를 생성합니다.

Type type = asm.GetType("HelloLib.ExampleClass");

 

3. 리플렉션된 type의 원 형식의 개체 생성

사용해 왔던 코드에서 비교하면 new와 같은 CreateInstance로 해당 클래스의 정보를 가지는 type개체를 가지고 obj를 생성합니다.

(만일 사용되는 클래스가 객체 생성을 필요치 않는 static과 같은 클래스라면 해당 코드는 생략해도 됩니다.)

Object obj = Activator.CreateInstance(type);

 

4. 멤버 메소드 리플렉션

HelloLib내의 Soo함수를 사용하기

아래 와 같은 방식으로 Dll내의 함수들을 사용할 수 있습니다.

사용하고자 하는 해당 함수의 정보를 GetMethod를 이용해 Method정보를 가질 수 있는 MethodInfo mi에게 정보를 가지게 하고 해당 Soo함수의 매개변수의 개수에 맞는 Object[] 배열을 만들어 거기에 넣어줍니다.

MethodInfo mi = type.GetMethod("Soo");

Object[] objs = new object[2];

objs[0] = 2;

objs[1] = 3;

 

 

5. 리플렉션된 메소드를 통한 원 개체의 원 메소드를 호출

Method 내의 Invoke를 통해 함수를 실행 시킬 수 있습니다.

해당함수의 정보를 가지고 있는 obj개체와 함수 구동에 필요한 매개변수들을 배열로 가진 objs를 넣어주면 해당함수가 실행됩니다.

함수를 선언해놓은 대로 return값을 받아 올 수 있습니다.

int re = (int)mi.Invoke(obj, objs);

Console.WriteLine("re:{0}", re);

 

6. 정적 멤버 메소드 리플렉션

mi = type.GetMethod("Koo");

           

 

//리플렉션된 정적 메소드를 통한 원 메소드를 호출

objs = new object[2];

objs[0] = 3;

objs[1] = 4;

re=(int) mi.Invoke(null, objs); //첫번째 인자가 null을 주는 것이 차이점           

Console.WriteLine("re:{0}", re);

 

7. 멤버 메소드 리플렉션

매개 변수가 없는 함수를 호출 하는 방식입니다.

mi = type.GetMethod("Foo");//리플렉션된 메소드를 통한 원 개체의 원 메소드를 호출

mi.Invoke(obj, null);

 

8. 프로퍼티 리플렉션

해당클래스의 속성을 이용하는 방식입니다 일단 GetProperty를 이용해서 프로퍼티의 정보를 PropertyInfo pi에 가지고 옵니다.

주의점은 as연산자를 사용할 수 없다는 것입니다.

이유는 as는 참조형식에 대한 변환이기 때문입니다.

PropertyInfo pi = type.GetProperty("Num");

 

int num = (int)pi.GetValue(obj, null); //리플렉션된 프로퍼티를 통해 원 개체의 원 프로퍼트의 Get사용

Console.WriteLine("num:{0}", num);

 

MethodInfo mi3 = pi.GetSetMethod();//리플렉션된 프로퍼티를 통해 Set메소드 리플렉션

object[] objs2 = new object[1];

objs2[0] = 7;

 

mi3.Invoke(obj, objs2); //리플렉션된 Set메소드를 통해 원 개체의 원 프로퍼티의 Set사용

 

mi3 = pi.GetGetMethod();//리플렉션된 프로퍼티를 통해 Get메소드 리플렉션

 

num = (int)mi3.Invoke(obj, null); //리플렉션된 Set메소드를 통해 원 개체의 원 프로퍼티의 Get사용

Console.WriteLine("num:{0}", num);

 

9.인덱서를 리플렉션으로 사용하는 방법입니다.

//인덱서의 set  리플렉션의

mi5 = type.GetMethod("set_Item");

objs = new object[2];

objs[0] = 7;

objs[1] = "하이" ;

//리플렉션 된 인덱서의 set을 통해 원 개체의 인덱서 set사용

mi5.Invoke(obj, objs);           

 

//인덱서의 get  리플렉션의

mi5 = type.GetMethod("get_Item");

objs = new object[1];

objs[0] = 7;

//리플렉션 된 인덱서의 get을 통해 원 개체의 인덱서 get사용

Console.WriteLine(mi5.Invoke(obj, objs).ToString());

 

10.델리게이트 와 이벤트를 리플렉션으로 사용하는 방법입니다.

//델리게이트 형식 리플렉션

Type type2 = asm.GetType("HelloLib.MyDele");

 

//이벤트 리플렉션

EventInfo ei = type.GetEvent("del");

 

//접근 권한이 public 하지 않으면서 정적인 메소드 리플렉션

MethodInfo mi8 = typeof(Program).GetMethod("DoIt"BindingFlags.NonPublic |BindingFlags.Static);

 

//형식 리플렉션

Type type3 = Type.GetType("AboutReflection.Program");           

           

//델리게이트가 리플렉션된 형식과 리플렉션된 메소드를 통한 델리게이트 개체 생성

Delegate d = Delegate.CreateDelegate(type2,mi8);

 

 

//리플렉션된 이벤트를 가지고 원 개체에 델리게이트(이벤트 핸들러) 추가

ei.AddEventHandler(obj, d);


리플렉션활용


기존에 만들엇던 dll을 직접 등록하지 않고 런타임시 dll을 로딩해 사용하도록 하였다.


  class Program

    {
        static void Main(string[] args)
        {
            Assembly asm = Assembly.Load("SumBit");
            Type type = asm.GetType("SumBitS.SumBit");
            Object obj = Activator.CreateInstance(type);
            MethodInfo mi = type.GetMethod("Run");
            mi.Invoke(obj,null);
        }
    }


'Programing > C#&.Net' 카테고리의 다른 글

인덱서(Indexer) 예제  (0) 2016.11.30
Delegate(대리자) 프로그램  (0) 2016.11.30
리플렉션(reflection)  (0) 2016.11.30
어셈블리,메타데이터  (0) 2016.11.30
형식 메타데이터  (0) 2016.11.30

리플렉션


.NET 환경에서 리플렉션은 런타임에 형식에 대한 정보를 얻는 과정이다. 리플렉션 서비스를 이용하면, 런타임에 어셈블리를 로드할 수 있고, ildasm 메타데이터 창에서 볼 수 있었던 것과 같은 종류의 정보를 찾아낼 수 있다. 

리플렉션을 이용해 해당 어셈블리에 포함되어 있는 모든 형식들의 목록과 각 형식에 정의된 메소드,필드,속성 그리고 이벤트 등을 얻어낼 수 있다. 또한 해당 클래스가 지원하는 인터페이스나,메소드의 매개변수뿐만 아니라 기타 관련 내용들(기본클래스의 상세내용, 네임 스페이스 정보, 매니페스트 데이터 등)도 동적으로 찾아낼 수 있다.

'Programing > C#&.Net' 카테고리의 다른 글

Delegate(대리자) 프로그램  (0) 2016.11.30
리플렉션 활용  (0) 2016.11.30
어셈블리,메타데이터  (0) 2016.11.30
형식 메타데이터  (0) 2016.11.30
c# 프로그램 연습  (0) 2016.11.30

+ Recent posts