English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

C# 반영(Reflection)

반영은 프로그램이 자신의 상태나 행동을 접근하고 검사하고 수정할 수 있는 능력을 의미합니다。

프로그램 집합은 모듈을 포함하며, 모듈은 타입을 포함하며, 타입은 멤버를 포함합니다. 반영은 프로그램 집합, 모듈, 타입을 포장하는 객체를 제공합니다。

반영을 사용하여 타입의 예제를 동적으로 생성할 수 있으며, 타입을 기존 객체에 바인딩하거나 기존 객체에서 타입을 가져올 수 있습니다. 그런 다음, 타입의 메서드를 호출하거나 그 필드와 속성에 접근할 수 있습니다。

점점과 단점

점점:

  • 1、반영은 프로그램의 유연성과 확장성을 높입니다。

  • 2、결합도를 낮추고 자율적 능력을 높입니다。

  • 3、프로그램은 어떤 클래스의 객체도 생성하고 제어할 수 있으며, 대상 클래스를 미리 코드로 설정할 필요가 없습니다。

단점:

  • 1、성능 문제:반영은 주로 설명 작업으로, 필드와 메서드에 접근할 때 직접 코드보다 느릴 수 있습니다. 따라서 반영 메커니즘은 유연성과 확장성이 매우 높은 시스템 프레임워크에 주로 적용되며, 일반 프로그램에서는 사용하지 않는 것이 좋습니다。

  • 2、反射는 프로그램 내부 로직을 흐리게 만들 수 있습니다;프로그래머는 소스 코드에서 프로그램의 로직을 볼 것을 원하지만, 반영은 소스 코드를 돌파하는 기술을 통해 로직을 흐리게 만들어, 유지보수 문제를 야기할 수 있습니다. 반영 코드는 해당 직접 코드보다 복잡합니다。

反射(Reflection)의 용도

反射(Reflection)의 용도는 다음과 같습니다:

  • 이는 실행 중에 특성(attribute) 정보를 확인할 수 있게 합니다.

  • 모음에서 다양한 타입을 검토하고 이러한 타입을 인스턴스화할 수 있게 합니다.

  • 메서드와 프로퍼티(property)의 지연 바인딩을 허용합니다.

  • 이는 실행 중에 새로운 타입을 생성하고 이러한 타입을 사용하여 일정한 작업을 수행할 수 있게 합니다.

메타데이터 확인

우리는 위의 장에서 이미 언급했듯이, 반영(Reflection)을 사용하여 특성(attribute) 정보를 확인할 수 있습니다.

System.ReflectionMemberInfo 객체는 초기화되어야 하며, 클래스와 관련된 특성(attribute)을 발견하기 위해 사용됩니다. 이를 위해 다음과 같이 타겟 클래스의 객체를 정의할 수 있습니다:

System.Reflection.MemberInfo info = typeof(MyClass);

아래 프로그램은 이를 보여줍니다:

using System;
[AttributeUsage(AttributeTargets.All)]
public class HelpAttribute : System.Attribute
{
   public readonly string Url;
   public string Topic  // Topic은 이름(named) 파라미터입니다
   {
      get
      {
         return topic;
      }
      set
      {
         topic = value;
      }
   }
   public HelpAttribute(string url)  // url은 위치(positional) 파라미터입니다
   {
      this.Url = url;
   }
   private string topic;
}
[HelpAttribute("MyClass 클래스에 대한 정보")]
class MyClass
{
}
namespace AttributeAppl
{
   class Program
   {
      static void Main(string[] args)
      {
         System.Reflection.MemberInfo info = typeof(MyClass);
         object[] attributes = info.GetCustomAttributes(true);
         for (int i = 0; i < attributes.Length; i++)
         {
            System.Console.WriteLine(attributes[i]);
         }
         Console.ReadKey();
      }
   }
}

위의 코드가 컴파일되고 실행될 때, 클래스에 추가된 MyClass 에 대한 커스텀 특성을 사용하겠습니다:

HelpAttribute

온라인 예제

이 예제에서는, 이전 장에서 생성한 DeBugInfo 특성을 사용하여 반사(Reflection)를 통해 읽습니다 Rectangle 클래스의 메타데이터.

using System;
using System.Reflection;
namespace BugFixApplication
{
   // BugFix라는 사용자 정의 특성이 클래스와 멤버에 할당되었습니다
   [AttributeUsage(AttributeTargets.Class |
   AttributeTargets.Constructor |
   AttributeTargets.Field |
   AttributeTargets.Method |
   AttributeTargets.Property,
   AllowMultiple = true)]
   public class DeBugInfo : System.Attribute
   {
      private int bugNo;
      private string developer;
      private string lastReview;
      public string message;
      public DeBugInfo(int bg, string dev, string d)
      {
         this.bugNo = bg;
         this.developer = dev;
         this.lastReview = d;
      }
      public int BugNo
      {
         get
         {
            return bugNo;
         }
      }
      public string Developer
      {
         get
         {
            return developer;
         }
      }
      public string LastReview
      {
         get
         {
            return lastReview;
         }
      }
      public string Message
      {
         get
         {
            return message;
         }
         set
         {
            message = value;
         }
      }
   }
   [DeBugInfo(45, "Zara Ali", "12/8/2012"
        Message = "Return type mismatch")]
   [DeBugInfo(49, "Nuha Ali", "10/10/2012"
        Message = "Unused variable")]
   class Rectangle
   {
      // 성원 변수
      protected double length;
      protected double width;
      public Rectangle(double l, double w)
      {
         length = l;
         width = w;
      }
      [DeBugInfo(55, "Zara Ali", "19/10/2012"
           Message = "Return type mismatch")]
      public double GetArea()}
      {
         return length * width;
      }
      [DeBugInfo(56, "Zara Ali", "19/10/2012)
      public void Display()
      {
         Console.WriteLine("长度: {0}", length);
         Console.WriteLine("宽度: {0}", width);
         Console.WriteLine("面积: {0}", GetArea());
      }
   }//end class Rectangle  
   
   class ExecuteRectangle
   {
      static void Main(string[] args)
      {
         Rectangle r = new Rectangle(4.5, 7.5);
         r.Display();
         Type type = typeof(Rectangle);
         // 遍历 Rectangle 类的特性
         foreach (Object attributes in type.GetCustomAttributes(false))
         {
            DeBugInfo dbi = (DeBugInfo)attributes;
            if (null != dbi)
            {
               Console.WriteLine("错误编号: {0}", dbi.BugNo);
               Console.WriteLine("开发者: {0}", dbi.Developer);
               Console.WriteLine("最后审查日期: {0}",
                                        dbi.LastReview);
               Console.WriteLine("备注: {0}", dbi.Message);
            }
         }
         
         // 遍历方法特性
         foreach (MethodInfo m in type.GetMethods())
         {
            foreach (Attribute a in m.GetCustomAttributes(true))
            {
               DeBugInfo dbi = (DeBugInfo)a;
               if (null != dbi)
               {
                  Console.WriteLine("错误编号: {0}, 用于方法: {1}
                                                dbi.BugNo, m.Name);
                  Console.WriteLine("开发者: {0}", dbi.Developer);
                  Console.WriteLine("最后审查日期: {0}",
                                                dbi.LastReview);
                  Console.WriteLine("备注: {0}", dbi.Message);
               }
            }
         }
         Console.ReadLine();
      }
   }
}

위의 코드가 컴파일되고 실행될 때, 다음과 같은 결과가 생성됩니다:

길이: 4.5
너비: 7.5
면적: 33.75
버그 번호: 49
개발자: Nuha Ali
최근 검토: 10/10/2012
备注: 사용되지 않은 변수
버그 번호: 45
개발자: Zara Ali
최근 검토: 12/8/2012
备注: 반환 타입 불일치
버그 번호: 55, Method: GetArea
개발자: Zara Ali
최근 검토: 19/10/2012
备注: 반환 타입 불일치
버그 번호: 56, Method: Display
개발자: Zara Ali
최근 검토: 19/10/2012
备注: