어트리뷰트(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());
}
}
}
SSISO Community