2013년 10월 25일 금요일

닷넷 c# 어트리뷰트, Attribute는 클래스안에 메타정보를 포함 시킬 수 있는...

닷넷 c# 어트리뷰트, Attribute는 클래스안에 메타정보를 포함 시킬 수 있는 기술로서 클래스, 데이터 구조, 열거자 그리고 어셈블리와 같은 프로그래밍적 요소들의 실행 시 행동에 대한 정보를 기술 할 수 있다.

다음과 같은 프로그래밍 요소에 대해 어트리뷰트를 사용 할 수 있다.
어셈블리모듈클래스구조체열거형 변수생성자메소드프로퍼티필드이벤트인터페이스파라미터반환 값델리게이트
 
어트리뷰트 역시 클래스의 일종이다.
 
어트리뷰트의 문법은 다음과 같다.
[attribute(positional_parameter, name_parameter = value, …) ]
파라미터에는 두 종류가 있는데 하나는 위치지정 파라미터로 반드시 들어와야 한다명명파라미터(name_parameter)는 꼭 필요하지는 않은 구조를 가지면 어트리뷰트 안에 추가적인 정보를 넣을 때 이용한다.
 
예를들면
 
[AdditionalInfo(“2011-01-01”)]
public class Test { ..}
 
 원하는 프로그래밍 요소 위에 Attribute를 써주면 그곳에 Attribute가 배정되는 것이다.
 
1.  Conditional Attribute
C# 디버깅을 지원하기 위해 Conditional Attribute를 사용 할 수 있다. Conditional Attribute는 사용자가 정의 한 값에 의해서 해당 메소드를 실행 하도록 한다.
 
#define SOUNDCARD // 이 부분을 지운 후 실행 해 보자
using System;
using System.Diagnostics;
 
class Test
{
       //Conditional Attribute인 경우 지정된 위치지정 파라미터가 정의 되어
       //있을 때 실행이 되는 것이다.
       [Conditional ("SOUNDCARD")]
       static void print()
       {
             Console.WriteLine("도레미...");
       }
 
       static void :namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />Main()
       {
             print();
       }
}
 
Conditional Attribute는 클래스나 구조체 안에 있는 메소드 에서만 사용 할 수 있다또 그 메소드는 void 형 이어야 한다다음의 예문처럼 메소드에 대해 여러 Conditional Attribute를 붙이게 되면 그 중 하나만 위치지정 파라미터가 정의 되어 있어도 그 메소드를 실행 시킨다.
 
만약 두개의 Conditional Attribute를 모두 만족해야 메소드를 실행 할려면 아래와 같은 방법을 이용하면 된다.
 
[Conditional(“MODEM”), Conditional(“ADSL”)]
static void print() { .. }
 
#define SOUNDCARD
#define SPEAKER
 
using System;
using System.Diagnostics;
 
class Test
{
      
       [Conditional ("SOUNDCARD")]
       static void isSound()
       {
             isSpeaker();
       }
 
       [Conditional ("SPEAKER")]
       static void isSpeaker()
       {
             Console.WriteLine("음악을 들을 수 있습니다...");
       }
 
       static void Main()
       {
             isSound();
       }
}
 
2.  DllImport 어트리뷰트
DllImport Attribute C#안에서 Unmanaged Code를 사용 할 수 있게 한다. Unmanaged Code란 닷넷 환경 밖에서 개발된 코드를 가리킨다. DllImport Attribute System.Runtime.InteropServices 네임스페이스 안에 정의 되어 있다사용방법은 위치지정 파라미터로 사용 할 DLL 파일을 인자로 넘겨 주면 된다.
 
using System;
using System.Runtime.InteropServices;
 
class Test
{
       //User32.dll 파일안의 MessageBox 함수를 불러와서 사용하는 예이다. DllImport Attribute
       //이용하여 사용할 코드가 포함되어 있는 DLL을 넘겨주고 extern키워드를 통해 사용하려고 하는
       //메소드가 외부에 있음을 알린다이렇게 하면 닷넷 환경 밖에서 개발된 코드들도 C#안에서 쓸 수 있다.
       [DllImport("User32.Dll")]
       public static extern int MessageBox(int h, string m, string c, int type);
 
       static void Main()
       {
             MessageBox(0, "Hello!", "In C#", 0);
       }
}
 
3.  Custom Attribute의 정의
 
-     어트리뷰트의 범위 지정
 
앞에서 Conditional Attribte는 메소드에만 붙일 수 있다고 했다그렇다면 사용자가 만든 어트리뷰트에 대해 어떤 곳에서만 붙일 수 있게 하는 방법은 없을까? AttributeUsage를 이용해서 사용자가 정의한 데이터 형에만 어트리뷰트를 붙일 수 있다.
 
[AttributeUsage(AttrbuteTargets.Method)]
public class AdditionalInfo { … }
 
AttributeUsage 역시 Attrbute 이며 사용자가 정의할 어트리뷰트 앞에 사용됨으로서 범위를 지정 할 수 있다. Method 이외에 AttrbuteTargets.Class, AttrbuteTargets.Delegate, AttrbuteTargets.Interface, AttrbuteTargets.Propert, AttrbuteTargets.Construct 등등을 사용 할 수 있다.
 
만약 여러 개의 데이터 형에 붙일려면 ‘|’를 이용하면 된다.
 
[AttributeUsage(AttrbuteTargets.Method | AttrbuteTargets.Delegate)]
public class AdditionalInfo { … }
 
또한 모든 데이터 형에 붙이는 것을 가능하게 할려면 AttrbuteTargets.All 이라고 해 주면 된다.
 
-     어트리뷰트 클래스 선언
 
간단히 클래스에 대한 제작자업데이트 날짜최신 버전을 다운 받을 수 있는 곳 등의 정보를 담을 수 있는 어트리뷰트를 만들어 보도록 하겠다다른 클래스를 만드는 것처럼 비슷하게 클래스를 작성 하면 어트리뷰트가 구현된다모든 어트리뷰트는 System.Attribute로 부터 상속 받는다즉 보통 클래스를 선언하는 똑 같은 방법으로 선언하고 다만 System.Attriute로부터 상속을 받으면 그 클래스가 어트리뷰트가 되는 것이다일반 클래스와 구분하기 위해 접미사로 ‘Attribute’를 붙일 것을 권고 한다.
 
어트리뷰트도 클래스 이므로 생성자가 존재 한다다만 어트리뷰트는 하나의 생성자만 가질 수 있다즉 생성자 오버로딩이 불가능 하다그럼 추가로 받아야 하는 정보들은 어떻게 처리 할까어트리뷰트에서는 생성자에서 꼭 집어 넣어야 하는 데이터는 위치지정 파라미터로 받고 부가적인 데이터는 명명 파라미터를 통해 받아 들임으로서 문제를 해결 한다.
 
[예제]
using System;
 
[AttributeUsage(AttributeTargets.Class)]
public class AdditionalInfoAttribute: Attribute
{
       //생성자에 있는 두개의 인자는 위치지정 파라미터 이다.
       //즉 위치지정 파라미터는 클래스에 어트리뷰트를 붙일때 반드시 넘겨 줘야 한다.
       //항상 생성자에서 값을 넘겨 주게 되어 있으므로 name, update인 경우 Property에서 set이 없다.
       public AdditionalInfoAttribute(string name, string update)
       {
             this.name = name;
             this.update = update;
       }
 
       public string Name
       {
             get { return name; }
       }
 
       public string Update
       {
             get { return update; }
       }
 
       public string Download
       {
             set { download = value; }
             get { return download; }
       }
 
       string name;
       string update;
       string download;
}
 
// 아래의 경우처럼 위치지정 파라미터는 생성자에 값을 그대로 전달하지만 명명 파라미
// 터는 파라미터 이름에 값을 대입하여 생성자에 넘겨야 한다.
[AdditionalInfo(“jclee”,’20094-01-01”, Download = http://www.oraclejavanew.kr)]
class Test { … }
 
 
클래스에 어트리뷰트를 붙였다면 반대로 클래스로부터 어떤 어트리뷰트들이 붙어 있는지 아는 하는 방법도 있어야 할 것이다바로 전 예제에서Test라는 클래스에 어트리뷰트를 붙였는데 반대로 Test라는 클래스로부터 어트리뷰트 정보를 알아내는 방법을 예제를 통해 보도록 하자.
 
public class AttrInfo
{
       public static void Main()
       {
             Type type = typeof(Test);
 
             foreach(Attribute attr in type.GetCustomAttributes(true))
             {
                    AdditionalInfoAttribute info = attr asAdditionalInfoAttribute;
 
                    if (info != null)
                    {
                           Console.WriteLine("Name={0}, Update={1}, DownLoad={2}", info.Name, info.Update, info.Download);
                    }
             }
       }
}
4.  사용자정의 어트리뷰트의 처리 과정
 
-     어트리뷰트 클래스를 찾는다.
-     어트리뷰트의 범위를 체크 한다.
-     어트리뷰트의 생성자를 체크 한다.
-     객체의 인스턴스를 생성 한다.
-     명명 파라미터들을 체크 한다.
-     명명 파라미터 값으로 필드나 프로퍼티의 값을 설정 한다.
-     어트리뷰트 클래스의 현재 상태를 저장한다.

댓글 없음:

댓글 쓰기