C# 反射

反射是指程序访问、发现和修改自身状态和行为的能力。反射提供用于描述程序集、模块和类型的对象。反射允许您动态实例化和绑定类型。获取现有对象或从现有对象获取类型以调用其方法或访问其字段和属性。如果您的代码使用属性,您还可以使用反射来访问它们。

使用反射

C# 中的反射有以下用途:

  • 在运行时显示视图属性信息。
  • 探索程序集中的不同类型并实例化这些类型。
  • 后期绑定到方法和属性。
  • 在运行时创建新类型并使用这些类型来执行某些任务。

显示元数据

前面我们提到可以使用反射来显示某个特性的信息,那么我们来看看具体的步骤。首先,我们需要初始化 System.Reflection 类的 MemberInfo 对象以发现与该类关联的属性。例如:

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

完整的示例代码为:

 using System;

[AttributeUsage(AttributeTargets.All)]
public class HelpAttribute : System.Attribute {
    public readonly string Url;
  
    public string Topic   // Topic は name_parameterです
    {
        get {
            return topic;
        }
        set {
            topic = value;
        }
    }
    public HelpAttribute(string url)   // url は positional_parametersです
    {
        this.Url = url;
    }
    private string topic;
}

[HelpAttribute("MyClassについての情報")]
class MyClass {

}

namespace it-kiso.com
{
    class Demo
    {
        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();
        }
    }
} 

操作的结果将是:

HelpAttribute

[示例] 此示例使用上一节中创建的 DeBugInfo 功能,并使用 Reflection 读取 Rectangle 类的元数据。

 using System;
using System.Reflection;

namespace it-kiso.com
{
    // クラスやメンバーに割り当てるカスタム属性のデバッグ修正プログラム
    [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 = "戻り値の型が一致しません")]
    [DeBugInfo(49, "Nuha Ali", "10/10/2012", Message = "未使用の変数")]

    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 = "戻り値の型が一致しません")]
        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());
        }
    }

    class Demo
    {
        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();
        }
    }
} 
反射是指程序访问、发现和修改自身状态和行为的能力。反射提供用于描述程序集、模块和类型的对象。反射允许您动态实例化和绑定类型。获取现有对象或从现有对象获取类型以调用其方法或访问其字段和属性。如果您的代码使用属性,您还可以使用反射来访问它们。

使用反射

C# 中的反射有以下用途:

  • 在运行时显示视图属性信息。
  • 探索程序集中的不同类型并实例化这些类型。
  • 后期绑定到方法和属性。
  • 在运行时创建新类型并使用这些类型来执行某些任务。

显示元数据

前面我们提到可以使用反射来显示某个特性的信息,那么我们来看看具体的步骤。首先,我们需要初始化 System.Reflection 类的 MemberInfo 对象以发现与该类关联的属性。例如:

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

完整的示例代码为:

 using System;

[AttributeUsage(AttributeTargets.All)]
public class HelpAttribute : System.Attribute {
    public readonly string Url;
  
    public string Topic   // Topic は name_parameterです
    {
        get {
            return topic;
        }
        set {
            topic = value;
        }
    }
    public HelpAttribute(string url)   // url は positional_parametersです
    {
        this.Url = url;
    }
    private string topic;
}

[HelpAttribute("MyClassについての情報")]
class MyClass {

}

namespace it-kiso.com
{
    class Demo
    {
        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();
        }
    }
} 

操作的结果将是:

HelpAttribute

[示例] 此示例使用上一节中创建的 DeBugInfo 功能,并使用 Reflection 读取 Rectangle 类的元数据。

 using System;
using System.Reflection;

namespace it-kiso.com
{
    // クラスやメンバーに割り当てるカスタム属性のデバッグ修正プログラム
    [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 = "戻り値の型が一致しません")]
    [DeBugInfo(49, "Nuha Ali", "10/10/2012", Message = "未使用の変数")]

    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 = "戻り値の型が一致しません")]
        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());
        }
    }

    class Demo
    {
        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();
        }
    }
}