SSISO Community

갤러리정

어트리뷰트(Attribute)와 리플렉션(Reflection) - CSharp

어트리뷰트(Attribute)
- 런타임시 필요한 정보들을 전달
- 클래스, 구조체, 열거형, 어셈블리 등에 정보제공
- 일종의 특수한 주석, 프로그래밍 가능
- [어트리뷰트명(지정위치 파라미터, 명명파라미터)]
- 내장 어트리ㅤㅂㅠㅌ트 & 사용자 어튜리뷰트
- 일반 어트리뷰트, COM호환 어트리뷰트, 트랜잭션 어트리뷰트, 비주얼 디자이너 컴포넌트 생성 어트리뷰트
- Conditional, DllImport, Obsolete

 

Conditional
- 디버깅에 사용
- #define 심볼의 유무에 따라서 호출이 결정되는 조건부 메서드를 만들 때 사용
- 메소드 반환형은 void 이어야 함.
- override 메소드에선 사용불가
- 인터페이스 구현 멤버 메소드에서도 사용 불가
- 반드시 System.Diagnostics를 using 해야함.
- 전처리기
- [Conditional("DEBUG")]

 

#define DEBUG       //DEBUG 어트리뷰트 사용
// #undef DEBUG     //어튜리뷰트 사용 해제

using System;
using System.Diagnostics;

namespace CSharpStudy
{
    class  MainClass
    {
        [Conditional("DEBUG")]
        public static void DebugPrint()
        {
            Console.WriteLine("Debug");
        }
        //프로그래밍시 디비깅 중간 점검용 메소드를 Conditional 어튜리뷰트로 선언해서 분리해 놓고
        //프로그램 중간중간 해당 메소드를 불러서 프로그램의 정상적인 실행여부를 체크하고자 할때 유용하게 사용할수있다.
        //#define를 선언하지 않으면 프로그램내에서 메소를 호출했다하더라도 실행되지 않으므로
        //프로그래밍시에는 #define을 선언해서 사용, 컴파일시에는 define하지 않으면 실행되지 않음, 컴파일에 포함되지 않음(?)

 

        [STAThread]
        static void Main(string[] args)
        {
            DebugPrint();

        }
    }
}

 

DllImport
- 외부 DLL을 호출하기 위한 어트리뷰트
- 사용하고자 하는 외부 DLL의 메소드 형식을 이미 알고있어야 함.
- System. Reuntime,InteropServices 를 using 해야함.
- C#에서 구현할 수 없는 것이나 다른 언어로 만든 dll을 사용하고자 할 때 사용할때 유용

 

 //시스템에 이미 등록되어있는 Win32 API Dll을 사용한 예제

using System;
using System.Runtime.InteropServices;   //호환되지 않은 Dll을 사용할때

namespace CSharpStudy
{
    class  MainClass
    {
        [DllImport("User32.Dll")]       //사용하려는 메서드에서 DllImport Attribute를 지정, 호출할 DLL의 이름을 기입
        public static extern int MessageBox(int i, string text, string title, int type);
        // 외부의 비관리(Unmanaged)코드에 있는 DLL을 특정 프로세스 메모리에 로딩하여
        // 이 함수의 메모리 주소를 MessageBox() 메서드에 지정
        // MessageBox()를 메서드 포인터처럼 사용함으로 C#에서 호출이 가능함
        // extern 키워드 : 어떤 메서드가 현재 프로그램 외부에 있음을 나타내는 키워드
       
        [DllImport("kernel32.dll")]
        private static extern bool Beep(int freq, int dur);

        [STAThread]
        static void Main(string[] args)
        {
            MessageBox(0, "MessageBox Text", "DllImport Test", 2);
            Beep(2600,1000);

        }
    }
}

 

Obsolete
- 더 이상 사용되지 않기를 권장하는 오래된 멤버를 구현할 때 사용

 

using System;

namespace CSharpStudy
{
    class  MainClass
    {
        //MethodOld 메소드 사용시 컴파일 할때 경고발생, 컴파일은 할수있음.
        [Obsolete("오래된 버전입니다. MethodNew()를 사용하세요.")]
        public static void MethodOld()
        {
            Console.WriteLine("Old");
        }

        public static void MethodNew()
        {
            Console.WriteLine("New");
        }

        [STAThread]
        static void Main(string[] args)
        {
            MethodOld();

        }
    }
}

 

리플렉션(Reflection)
- 런 타임시에 객체에 대한 정보를 질의하는 방법-> 실행시에 객체를 통해 클래스의 정보를 분석해내는 프로그램 기법
- using System.Reflection;
- System.Type 클래스를 이용

 

리플렉션(Reflection) 기법의 사용
- 메모리를 보유하고 있는 객체가 존재할 경우
- 객체의 형(Type) 정보를 알아낸다. (즉, 해당 객체의 Type 클래스 생성)
- 생성된 Type과 해당 객체의 메모리를 이용하여 멤버들을 호출

 

리플렉션(Reflection)의 기법
- 클래스의 능력(멤버메서드, 멤버필드 등)을 실행시에 분석
- 객체들의 속성(객체의 소속 등)을 실행시에 검사

 

리플렉션(Reflection) 기법으로 얻을 수 있는 정보
- 로딩된 Assembly에 관한 정보
- 클래스, 인터페이스 그리고 값타입의 형들에 관한 정보
 
객체의 Type가져오기
- typeof 연산자 : 클래스 타입으로 접근할 때 사용
- System.Object의 GetType() : 객체명으로 접근할 때 사용 -> 객체.GetType();
- Type.GetType() : 네임스페이스로 접근할 때 사용
- Assembly.LoadFrom() :  dll 파일에 직접 접근할 때 사용

 

using System;
using System.Reflection;

public class GetTypeTest {
    public static void Main() {

        //1. dll 파일로 접근하는 방법
        Assembly a = Assembly.LoadFrom("C:\\WINNT\\Microsoft.NET\\Framework\\v1.0.3705\\System.dll");
        //LoadFrom() 메서드 : 로드하고자 하는 파일의 경로와 파일의 확장자까지 입력해야 사용

        //Assembly a = Assembly.Load("System");
        //Load() 메서드 : 경로를 지정불가, 실행파일이 있는 현재의 디렉터리를 기준으로 dll을 로딩후 파일의 확장자를 제외한 파일의 이름만을 사용.  결과로 출력된 822라는 것은 System.dll 파일 안에 존재하는 Type 클래스의 개수.

        Type [ ] type = a.GetTypes();
        Console.WriteLine(type.Length);         // 결과 :  822

        /*
        foreach(Type t in type){
            Console.WriteLine(t.FullName);
        }
        */

 

        //2. 객체로 접근하는 방법
        string s = "jabook";
        Type t1 = s.GetType();
        Console.WriteLine(t1);           //결과 : System.String

 

        //3. 런타임 시 지정된 이름으로 접근하는 방법
        Type t2 = Type.GetType("System.String");
        Console.WriteLine(t2);       //결과 : System.String
        
        //4. 클래스 타입으로 접근하는 방법
        Type t3 = typeof(System.String);
        Console.WriteLine(t3);       //결과 : System.String
       
    }
}

 

* Type을 이용하여 클래스의 정보 추출

    using System;
    using System.Reflection;

    public class TypeInfoTest {
        public int temp =1000;
        public void PrintShow(){ }
        public static void Main() {
            try{


                Type t = Type.GetType("TypeInfoTest");

                Console.WriteLine("[기본클래스 타입]");
                Console.WriteLine(t.BaseType);
                // BaseType 속성은 Type 클래스의 읽기전용 속성, 현재 Type 클래스가 직접 상속하는 클래스 타입(이름)을 반환.
                // 만약, Object 클래스의 Type 클래스라면 상속하는 클래스가 없으므로 null을 반환.

 

                Console.WriteLine("[생성자 목록]");
                ConstructorInfo[ ] ctor = t.GetConstructors();
                for(int i=0;i<ctor.Length;i++)
                Console.WriteLine(ctor[i]);

 

                Console.WriteLine("[메서드 목록]");
                MethodInfo[ ] m = t.GetMethods();
                for(int i=0;i<m.Length;i++)
                Console.WriteLine(m[i]);

 

                Console.WriteLine("[변수 목록]");
                FieldInfo[ ] f = t.GetFields();
                for(int i=0;i<f.Length;i++)
                    Console.WriteLine(f[i]);
            }
            catch(Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
    }


1313 view

4.0 stars