于梦想齐行
于梦想齐行

C#特性(Attribute)&反射(Reflection)

C#特性(Attribute)&反射(Reflection)
#define DEBUG_MODE
using System;
using System.Reflection;
using System.Diagnostics;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            //C# 特性(Attribute)
            /*
             * 特性(Attribute)是用于在运行时传递程序中的各种元素(比如类、方法、结构、枚举、组件等)的行为信息的声明性标签。您可以通过使用特性向程序添加声明性信息。一个声明性标签是通过放置在它所应用的元素前面的方括号([])来描述的。
             * 特性(Attribute)用于添加元数据,如编译器指令和注释、描述、方法、类等其他信息。.Net框架提供了两种类型的特性:预定义特性和自定义特性
             * 
             * 规定特性(Attribute)
             * 语法:[attribute(positional_parameters, name_parameter = value, ...)] element
             * positional_parameters规定必须的信息
             * name_parameter规定可选的信息
             * 
             * 预定义特性(Attribute)
             * .Net框架提供了三种预定义特性:
             * 1.AttributeUsage
             * 2.Conditional
             * 3.Obsolete
             * 
             * AttributeUsage:描述了如何使用一个自定义特性类。它规定了特性可应用到的项目的类型。
             * [AttributeUsage(
             *     validon,
             *     AllowMultiple allowmultiple,
             *     Inherited inherited
             * )]
             * 其中:
             * validon规定特性可被放置的语言元素。它是枚举器AttributeTargets的值的组合。默认是AttributeTargets.All
             * allowmultiple(可选的)为该特性的AllowMultiple属性(property)提供一个布尔值。如果为true,则该特性是多用的。默认值是false(单用的)。
             * inherited(可选的)为该特性的Inherited属性(property)提供一个布尔值。如果为true,则该特性可以被派生类继承。默认值为false(不被继承)。
             * 
             * 例如:
             * [AttributeUsage(AttributeTargets.Class |
             *  AttributeTargets.Constructor |
             *  AttributeTargets.Field |
             *  AttributeTargets.Method |
             *  AttributeTargets.Property,
             *  AllowMultiple = true)]
             *  
             *  Conditional
             *  这个预定义特性标注了一个条件方法,其执行依赖于指定的预处理标识符
             *  他会引起方法调用的条件编译,取决于指定值,比如Debug或Trace。例如,当调试代码时显示变量的值。
             *  语法:
             *  [Conditional(
             *      conditionalSymbol
             *  )]
             *  例如:
             *  [Conditional("DEBUG")]
             */
            //实例
            MyClass.Message("in main func");
            func1();

            //Obsolete
            //这个预定义特性标记了不应被使用的程序实体。它可以让您通知编辑器丢弃某个特定的目标元素。例如:当一个新方法被用在一个类中,但是您仍然想要保持类中的旧方法,您可以通过显示一个应该使用新方法,而不是旧方法的消息,来把它标记为obsolete(过时的)
            /*语法:
             * [Obsolete(
             *     message
             * )]
             * [Obsolete(
             *     message,
             *     iserror
             * )]
             * 其中:
             * message是一个字符串,描述项目为什么过时以及该替代使用什么
             * iserror是一个布尔值,如果该值为true,编译器应把该项目的使用当作一个错误。默认值false(编译器生成一个警告)
             */
            //实例
            //OldMethod();

            //创建自定义特性(Attribute)
            /*
             * .net框架允许创建自定义特性,用于存储声明性的信息,且可在运行时被检索。该信息根据设计标准和应用程序需要,可与任何目标元素相关
             * 创建并使用自定义特性包含四个步骤
             * 声明自定义特性->构建自定义特性->在目标程序元素上应用自定义特性->通过反射访问特性
             * 最后一个步骤是编写程序来读取元数据以查找各种符号。元数据是用于描述其他数据的数据和信息。该程序应使用反射来在运行时访问特性。
             * 
             * 声明自定义特性
             * 一个新的自定义特性应派生自System.Attribute类
             * //一个自定义特性BugFix被赋给类及其成员
             * [AttributeUsage(AttributeTargets.Class |
             * AttributeTargets.Constructor |
             * AttributeTargets.Field |
             * AttributeTargets.Method |
             * AttributeTargets.Property,
             * AllowMultiple = true
             * )]
             * public class DeBugInfo: System.Attribute
             * 
             * 构建自定义特性
             * 该特性将存储调试程序获得的信息,它存储以下信息:
             * bug的代码编号
             * 辨认该bug的开发人员名字
             * 最后一次审查该代码的日期
             * 一个存储了开发人员标记的字符串消息
             * 
             * 我们的DeBugInfo类将带有3个用于存储前3个信息的私有属性(property)和一个用于存储消息的公有属性(property)。所以bug编号、开发人员的名字和审查日期将是DeBugInfo类必须的定位(positional)参数,消息将是一个可选的命名(named)参数。
             * 每个特性必须至少有一个构造函数。必需的定位(positional)参数应通过构造函数传递。
             * 
             * 见下DeBugInfo类
             * 
             * 
             * 应用自定义特性
             * 通过把特性放置在紧接着它的目标之前,来应用特性
             * 
             * 见下Rectangle类
             */

            //反射
            /*
             * 反射指程序可以访问、检测和修改它本身状态或行为的一种能力
             * 程序集包含模块,而模块包含类型,类型又包含成员。反射则提供了封装程序集、模块和类型的对象。
             * 你可以使用反射动态的创建类型的实例,将类型绑定到现有对象,或从现有对象获取类型。然后,调用类型的方法或访问其字段和属性。
             * 
             * 优点:
             * 1.反射提高了程序的灵活性和扩展性
             * 2.降低耦合性,提高自适应能力
             * 3.它允许程序创建和控制任何类的对象,无需提前硬编码目标类
             * 缺点:
             * 1.性能问题:使用反射基本上是一种解释操作,用于字段和方法接入时要远慢于直接代码。因此反射机制主要应用在对灵活性和扩展性要求很高的系统框架上,普通程序不建议使用。
             * 2.使用反射会模糊程序内部的逻辑;程序员希望在源代码中看到程序的逻辑,反射却绕过了源代码的技术,因此会带来维护问题,反射代码比相应的直接代码更复杂。
             * 
             * 
             * 反射(reflection)的用途
             * 1.它允许在运行时查看特性(attribute)信息
             * 2.它允许审查集合中的各种类型,以及实例化这些类型
             * 3.它允许延时绑定的方法和属性(property)
             * 4.它允许在运行时创建新类型,然后使用这些类型执行一些任务
             * 
             * 
             * 查看元数据
             * 使用反射可以查看特性信息
             * System.Reflection类的MemberInfo对象需要被初始化,用于发现与类相关的特性(attribute)。\
             * System.Reflection.MemberInfo info = typeof(MyClass);
             * 
             */
            System.Reflection.MemberInfo info = typeof(MyClass2);
            object[] attributes = info.GetCustomAttributes(true);
            for(int i = 0;i<attributes.Length;i++)
            {
                Console.WriteLine(attributes[i]);
            }

            //获取Rectangle上的DeBugInfo信息
            Rectangle r = new Rectangle(4.5, 7.5);
            r.Display();
            Type type = typeof(Rectangle);
            //遍历Rectangle类的特性
            foreach(Object attributes2 in type.GetCustomAttributes(false))
            {
                DeBugInfo dbi = (DeBugInfo)attributes2;
                if(null != dbi)
                {
                    Console.WriteLine("Bug no: {0}", dbi.BugNo);
                    Console.WriteLine("Developer: {0}", dbi.Developer);
                    Console.WriteLine("Last Reviewed: {0}", dbi.LastReview);
                    Console.WriteLine("Remarks: {0}", dbi.Message);
                }
            }
            //遍历方法特性
            foreach(MethodInfo mi in type.GetMethods())
            {
                foreach(Attribute ai in mi.GetCustomAttributes(true))
                    {
                    DeBugInfo dbi = (DeBugInfo)ai;
                    if (null != dbi)
                    {
                        Console.WriteLine("Bug no: {0}", dbi.BugNo);
                        Console.WriteLine("Developer: {0}", dbi.Developer);
                        Console.WriteLine("Last Reviewed: {0}", dbi.LastReview);
                        Console.WriteLine("Remarks: {0}", dbi.Message);
                    }
                }
            }
            Console.ReadKey();
         }

        [Obsolete("Don't use OldMethod, use NewMethod instead", true)]
        static void OldMethod()
        {
            Console.WriteLine("It is the old method.");
        }

        static void NewMethod()
        {
            Console.WriteLine("It is the new method.");
        }

        static void func1()
        {
            MyClass.Message("in func1.");
            func2();
        }

        static void func2()
        {
            MyClass.Message("in func2.");
        }
    }

    [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("Information on the class MyClass2")]
    class MyClass2
    {

    }

    [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("Length: {0}", length);
            Console.WriteLine("Width: {0}", width);
            Console.WriteLine("Area: {0}", GetArea());
        }

    }

    //一个自定义特性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;
        private string message;

        public DeBugInfo(int b, string dev, string d)
        {
            this.bugNo = b;
            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;
            }
        }
    }

    public class MyClass
    {
        //message only show on DEBUG_MODE
        [Conditional("DEBUG_MODE")]
        public static void Message(string msg)
        {
            Console.WriteLine(msg);
        }
    }
}
没有标签
首页      CSharp      C#特性(Attribute)&反射(Reflection)

于梦想齐行

C#特性(Attribute)&反射(Reflection)
#define DEBUG_MODE using System; using System.Reflection; using System.Diagnostics; namespace ConsoleApp1 { class Program { static void Main(string&…
扫描二维码继续阅读
2022-06-28
近期文章
近期评论