외로운 Nova의 작업실

c# 언어 공부 - 12(애트리뷰트) 본문

Programming/C#

c# 언어 공부 - 12(애트리뷰트)

Nova_ 2022. 5. 13. 21:34

안녕하세요. 저번시간에 이어서 오늘은 c#의 에트리뷰트에대해서 배워보도록 하겠습니다.

 

<에트리뷰트>

혹시 코딩하면서 잘못된 메소드나 코드를 짯을때 뜨는 error메시지를 본적이 있으신가요?

아래와 같은 메시지 말이죠!

이러한 메시지를 저장하는 곳이 에트리뷰트 클래스입니다!

백문일 불여일견! 바로 어떻게 하는지 코드부터 보시죠.

using System;


namespace StudyCSharp
{
    class MainApp
    {
        
        static void Main(string[] args)
        {

            Method OldMethod = new Method();

            OldMethod.OldMethod();

        }
        [Obsolete("OldMethod는 없어졌습니다. NewMethod를 사용하세요")] //애트리뷰트사용
        
        class Method
        {
            public void OldMethod()
            {
                Console.WriteLine("나는 옜날의 메소드입니다.");
            }
        }

    }

}

 

위 코드의 오류표시줄에는 아래와 같은 화면이 나타납니다.

[]괄호안 애트바뷰트 Obsolete() 매개변수안의 문장이 출력되는 것입니다.

그렇다면 프로그래머는 저 문장을 보고 아마도 NewMethod()를 사용하겟죠?

이렇게 애트리뷰트는 클래스를 설계하는 사람이 객체를 사용하는 사용자들에게 이용의 편의를 줍니다.

또한 자세히 말하면 코드에대한, 클래스에대한, 메소드에대한 정보들을 숨겨놓는것이죠!

원래는 주석이 있지만 저런 메시지는 클래스에 주석을 달겠죠..

하지만 우리는 클래스를 보지않고 클래스의 인스턴스로 바로씁니다.

System.Console.WriteLine()만 봐도 클래스를 보지않고, 즉 주석을 보지않고 static 메소드를 바로쓰죠

즉, 우리는 어떠한 메소드나 클래스를 사용할때 주석을 보지못하니 애트리뷰트를 사용해서 해당 메소드나 클래스에대한 정보들을 얻을 수 있습니다.

 

애트리뷰트에는 Obsolete()말고도 그 종류가 상당히 많습니다.

예를들어 DLL에 있는 함수를 호출할 떄 사용하는 [DLLImport] 애트리뷰트, 조건부 메소드 실행을 지정할때 사용하는 [Conditional]등이 그 예입니다.

하지만 애트리뷰트는 이미 만들어진것보다, 우리가 생성해서 쓰는 경우가 많습니다.

그래서 애트리뷰트를 직접 만들어보고 활용하는 방법을 알아보겠습니다.

저는 History 애트리뷰트를 만들어보겠습니다.

클래스의 역사 즉, 프로그래머이름, 버전, 변경이력을 표시해주는 애트리뷰트를 만들어보겠습니다.

먼저, 애트리뷰트는 역시 클래스입니다.

하지만 System.Attribute를 상속한 클래스죠.

또한 []괄호안에 들어가게됩니다.

History클래스를 만들고 사용해보겠습니다.

using System;


namespace StudyCSharp
{
    class MainApp
    {
        
        static void Main(string[] args)
        {
            Type TypeO = typeof(Myclass);
            Attribute[] AttributeO = Attribute.GetCustomAttributes((TypeO));

            foreach (Attribute attr in AttributeO)
            {
                History H = attr as History;
                Console.WriteLine($"Programmer : {H.Programmer}, Version : {H.Version}, Change : {H.Change}");
            }


        }

        class History : System.Attribute
        {
             public string Programmer;

            public double Version
            {
                get;
                set;
            }

            public string Change
            {
                get;
                set;
            }

            public History(string Programmer)
            {
                this.Programmer = Programmer;
                Version = 1.0;
                Change = "First Release";
            }
        }

        [History("Nova", Version = 2.0, Change = "Fix Bug")]
        class Myclass
        {
            public void Func()
            {
                Console.WriteLine("Func()");
            }
        }
    }

}

위코드는 Myclass에대한 변경이력을 History객체 담아서 클래스의 주석을 보지않고도 Main함수에서 Myclass의 변경이력을 직접 뽑아내서 콘솔에 출력합니다.

다시한번 말하지만 프로그램의 크기가 커질수록 클래스의 주석을 확인하지않고 객체로 바로 만들어 사용합니다.

주석을 확인하지않으니 그 객체나 메소드의 정보를 애트리뷰트를 통해 보는 것이지요.

 

위코드는 변경이력이 하나밖에 없습니다.

그렇다면 하나 더 추가해보도록 하겠습니다.

하나 더 추가할때는 애트리뷰트의 속성을 변경해줘야합니다.

원래 애트리뷰트는 하나밖에 사용을 못하거든요...

그럼 History 애트리뷰트의 속성을 변경해보겠습니다.

[System.AttributeUsage(System.AttributeTargets.Class, AllowMultiple = true)]
        class History : System.Attribute
        {
             public string Programmer;

            public double Version
            {
                get;
                set;
            }

            public string Change
            {
                get;
                set;
            }

            public History(string Programmer)
            {
                this.Programmer = Programmer;
                Version = 1.0;
                Change = "First Release";
            }
        }

History 애트리뷰트 위에 애트리뷰트의 속성을 변경하는 코드를 집어넣습니다.

System.AttribueUsage()메소드를 사용하여 속성을 변경합니다.

매개변수로는 첫번째 System.AttribueTargets.class는 애트리뷰트가 설명하는 것이 클래스인 메소드인지 알려주는것입니다.

만약 메소드라면 System.AttributeTarget.Method로 고칠 수 있습니다.

두번째 매개변수 AllowMultiple = true는 중복사용을 가능하게한다는 것입니다.

위 코드로 중복사용을 가능하게했습니다.

실제로 사용해보겠습니다.

using System;


namespace StudyCSharp
{
    class MainApp
    {
        
        static void Main(string[] args)
        {
            Type TypeO = typeof(Myclass);
            Attribute[] AttributeO = Attribute.GetCustomAttributes((TypeO));

            foreach (Attribute attr in AttributeO)
            {
                History H = attr as History;
                Console.WriteLine($"Programmer : {H.Programmer}, Version : {H.Version}, Change : {H.Change}");
            }


        }
        [System.AttributeUsage(System.AttributeTargets.Class, AllowMultiple = true)]
        class History : System.Attribute
        {
             public string Programmer;

            public double Version
            {
                get;
                set;
            }

            public string Change
            {
                get;
                set;
            }

            public History(string Programmer)
            {
                this.Programmer = Programmer;
                Version = 1.0;
                Change = "First Release";
            }
        }

        [History("Nova", Version = 2.0, Change = "Fix Bug")]
        [History("Nova2", Version = 3.0, Change = "Make Age")]
        class Myclass
        {
            public void Func()
            {
                Console.WriteLine("Func()");
            }
        }
    }

}

위 코드의 실행결과는 아래와 같습니다.

애트리뷰트

이런식으로 해당 클래스의 정보를 주석이 아닌 애트리뷰트로 볼 수 있습니다.

다시한번 말씀드리지만 애트리뷰트는 코드(클래서, 메소드등)에대한 정보를 담는 객체입니다...!

 

다음시간에는 dynamic 형식에대해서 배워보도록 하겠습니다.

Comments