zoukankan      html  css  js  c++  java
  • .NET C#利用反射获取类文件以及其中的方法&属性 并获取类及方法上的特性

    了解C#特性类并声明我们自己的特性类【AttributeTest】代码如下


    using System;
    
    namespace AttributeTest
    {
        /* 特性说明
        特性本质是一个继承和使用了系统基类的"类",用以将元数据或声明信息与代码(程序集、类型、方法、属性等)相关联。特性与程序实体关联后,
        即可在运行时使用名为“反射”的技术查询特性。
        官方介绍的很详细,我们就一起来了解一下它的用法。
    
        特性具有以下属性:
    
        1.特性可向程序中添加元数据。元数据是有关在程序中定义的类型的信息。所有的.NET 程序集都包含指定的一组元数据,
          这些元数据描述在程序集中定义的类型和类型成员。可以添加自定义特性,以指定所需的任何附加信息。
    
        2.可以将一个或多个特性应用到整个程序集、模块或较小的程序元素(如类和属性)。
    
        3.特性可以与方法和属性相同的方式接受参数。
    
        4.程序可以使用反射检查自己的元数据或其他程序内的元数据。
        */
    
        #region 声明一个 作用于成员方法 的特性
        //1.第一步 继承自定义属性的基类 Attribute
        //2.第二步 指定 我们自定义特性类 的一些属性,用系系统特性指定
        // AttributeTargets:指定为程序中的何种成员设置属性 可写多个 例: AttributeTargets.Class|AttributeTargets.Method
        //    AllowMultiple:如果允许为一个实例多次指定该特性,则为 true;否则为 false。默认为 false。
        //        Inherited:如果该属性可由派生类和重写成员继承,则为 true,否则为 false。默认为 true。
        [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
        public class MethodAttribute : Attribute 
        {
            /// <summary>
            /// 方法名称
            /// </summary>
            public string MethodName { set; get; }
            /// <summary>
            /// 方法描述
            /// </summary>
            public string MethodDesc { set; get; }
    
            /// <summary>
            /// 方法描述特性
            /// </summary>
            /// <param name="methodName">方法名称</param>
            /// <param name="methodDescription">方法描述</param>
            public MethodAttribute(string methodName, string methodDescription)
            {
                MethodName = methodName;
                MethodDesc = methodDescription;
            }
        }
        #endregion
    
        #region 声明一个 作用于类 的特性
        [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]//第一步
        public class ClassAttribute : Attribute//第二步
        {
            string ClassName { set; get; }
            string ClassDesc { set; get; }
    
            public ClassAttribute(string className, string classDesc)
            {
                ClassName = className;
                ClassDesc = classDesc;
            }
    
            //重写当前特性的ToString()方法
            public override string ToString()
            {
                return string.Format(@"当前类特性名:[ClassAttribute]
                    特性成员1:ClassName-->值:{0},
                    特性成员2:ClassDesc-->值:{1}", ClassName, ClassDesc);
            }
        }
        #endregion
    }
    

      

    编写使用了自定义特性类的类及成员 代码如下

    using System;
    
    namespace AttributeTest
    {
        #region 为一个类编写成员 并使用自定义的类特性以及成员特性 
        [ClassAttribute("TestClass", "测试反射及特性")]
        class TestClass
        {
            string _StrTest = "测试信息";
            float _Version = 1.1F;
            float Version { set { _Version = value; } get { return _Version; } }
            string StrTest { set { _StrTest = value; } get { return _StrTest; } }
    
            public TestClass()
            {
    
            }
    
            TestClass(string strTest,float version)
            {
                StrTest = strTest;
                Version = version;
            }
    
            #region 用于测试反射执行私有非静态方法(带有自定义方法成员特性)---> 成员1
            [MethodAttribute("Demo", "测试特性类示例方法Demo")]
            string Demo(string param)
            {
                return string.Format("
    1.方法调用信息:
    ①调用方法:{0}
    ②传递参数:{1}", "Demo", param);
            }
            #endregion
    
            #region 用于测试反射执行公开静态方法(带有自定义方法成员特性)---> 成员2
            [MethodAttribute("Demo1", "测试特性类示例方法Demo1")]
            public static string Demo1(string param)
            {
                return string.Format("
    1.方法调用信息:
    ①调用方法:{0}
    ②传递参数:{1}", "Demo1", param);
            }
            #endregion
    
            public void ConsoleMsg(string strMsg)
            {
                Console.WriteLine("
    Msg:"+strMsg);
            }    
        }
        #endregion
    
    }
    

     

    通过反射机制 获取所编写类文件及其成员 和其特性 代码如下

    using System;
    using System.Reflection;
    
    namespace AttributeTest
    {
        class Program
        {
            #region 存储 TestClass类反射信息 的字段
            static Type clazz;
            static Type clazz1;
            static Type clazz2;
            static Type clazz3;
            #endregion
    
            static void Main(string[] args)
            {
                Program program = new Program();    
                program.GetReflectInfoByClass();              //得到TestClass类的反射
                program.ReflectInvokePrivateNonStaticMethod();//反射的方式调用TestClass类中私有非静态方法 并输出其方法上的特性
                program.ReflectInvokePublicStaticMethod();    //反射的方式调用TestClass类中公开静态方法 并输出其方法上的特性
                program.GetAllField();                        //获取TestClass类中的 字段
                program.GetAllProp();                         //获取TestClass类中的 属性
                program.ReflectGetAttributeByClass();         //获取TestClass类上的 特性
    
                Console.ReadKey();
            }
    
            #region 通过【类名】和【类的限定名】和 【程序集(Assembly)】取得类的【反射信息】
            //通过类名和类的限定名取得类的反射信息
            void GetReflectInfoByClass()
            {
                //以下三种种方式得到当前类的反射信息 得到的结果都一样
    
                //1.通过TestClass类名得到类反射信息
                clazz = typeof(TestClass);
                clazz1 = new TestClass().GetType();
    
                //2.通过TestClass类的限定名得到其反射信息
                clazz2 = Type.GetType("AttributeTest.TestClass");
    
                //3.通过【程序集.dll】或【可执行文件.exe】反射TestClass
                Assembly assembly = Assembly.LoadFile(@"F:Projects_C#UpLoadData_prjAttributeTestinDebugAttributeTest.exe");
                clazz3 = assembly.GetType("AttributeTest.TestClass");
    
                //判别得到的反射是否一致
                if (clazz.Equals(clazz2) && clazz2.Equals(clazz3))
                    Console.WriteLine("
    clazz==clazz1==clazz2==clazz3
    ");
    
                //直接利用 程序集和类的完全限定名 创建TestClass对象 调其方法
                var obj = assembly.CreateInstance("AttributeTest.TestClass");
                if (obj is TestClass)
                {
                    TestClass tc = obj as TestClass;
                    tc.ConsoleMsg("反射会破坏访问权限");      
                }
            }
            #endregion
    
            #region 用反射的方式调用【TestClass类】私有非静态方法
            /// <summary>
            /// 用反射的方式调用TestClass类中私有非静态方法
            /// </summary>
            void ReflectInvokePrivateNonStaticMethod()
            {
                //Demo为私有方法 指定在类中搜索私有成员|实例成员
                BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Instance;
    
                //反射私有方法需要指定 BindingFlags.NonPublic
                var Demo = clazz1.GetMethod("Demo", bindingFlags);//私有非静态
    
                #region 调用私有非静态方法[Demo]
                //1.实例化[Demo]方法所在类, 第二个参数默认false:不可访问私有构造函数  true:则可访问类中私有构造函数
                object o = Activator.CreateInstance(clazz2, true);
    
                //2.通过类的实例调用方法[Demo] (含一个参数)
                var returns = Demo.Invoke(o, new object[] { "ReflectionTest" });
                Console.Write(returns);
                #endregion
    
                //输出方法上的特性信息
                ReflectGetAttributeByMethod(Demo);
                Console.Write("
    ");
            }
    
            #endregion
    
            #region 用反射的方式调用【TestClass类】中公开静态方法
            /// <summary>
            /// 用反射的方式调用TestClass类中公开静态方法
            /// </summary>
            void ReflectInvokePublicStaticMethod()
            {
                #region 调用公开静态方法
                //1.Demo1为公开访问权限,BindingFlags默认为 Instance、Public
                var Demo1 = clazz2.GetMethod("Demo1");
    
                //2.Demo1为静态方法 调用不需要实例化其所在类
                var returns = Demo1.Invoke(clazz, new object[] { "ReflectionTest1" });
    
                //输出方法返回值
                Console.Write(returns);
                #endregion
    
                //通过反射信息得到方法上的特性信息
                ReflectGetAttributeByMethod(Demo1);
                Console.WriteLine("
    ");
            }
            #endregion
    
            #region 通过 【方法反射信息】 得到方法使用的特性
            /// <summary>
            /// 通过方法的反射信息得到方法使用的特性
            /// </summary>
            /// <param name="method"></param>
            void ReflectGetAttributeByMethod(dynamic method)
            {
                if (method == null)
                {
                    Console.WriteLine("参数不能为空!,按任意键结束!");
                    Console.ReadKey();
                    return;
                }
    
                //得到当前方法上的特性类 信息
                MethodAttribute methodAttribute = Attribute.GetCustomAttribute(method, typeof(MethodAttribute));
                if (methodAttribute != null)
                {
                    Console.WriteLine("
    2.输出当前方法特性信息:");
                    Console.WriteLine("①当前调用方法名称:[" + methodAttribute.MethodName + "]");
                    Console.WriteLine("②方法描述:[" + methodAttribute.MethodDesc + "]");
                }
                else
                {
                    Console.WriteLine("
    当前传入的方法没有反射信息!
    ");
                }
            }
    
            #endregion
    
            #region 获取【类】的 特性 信息
            /// <summary>
            /// 获取修饰类的 特性 信息
            /// </summary>
            void ReflectGetAttributeByClass()
            {
                Attribute attribute = Attribute.GetCustomAttribute(clazz2, typeof(Attribute));
                if (attribute != null)
                {
                    Console.WriteLine(attribute.ToString());
                }
            }
            #endregion
    
            #region 获取【字段】并得其值
            //获取字段并得到字段的值
            void GetAllField()
            {
                //获取构造函数 公开无参的构造方法
                var constructor = clazz.GetConstructor(new Type[0]);
    
                //通过构造函数的调用获取对象
                var TestClass = constructor.Invoke(new object[0]);
    
                //获取所 实例 私有 字段
                FieldInfo[] fields = clazz.GetFields(BindingFlags.Instance|BindingFlags.NonPublic);
                
                //循环遍历字段和其值
                foreach (FieldInfo field in fields)
                {
                    Console.WriteLine("
    字段:"+field.Name+",值:"+field.GetValue(TestClass).ToString()+"
    ");
                }
            }
    
            #endregion
    
            #region 获取【属性】并得其值
            //获取属性并得到属性的值
            void GetAllProp()
            {
                //获取有两个参数私有非静态的构造方法
                var constructor = clazz.GetConstructor(
              BindingFlags.Instance|BindingFlags.NonPublic,//方法修饰符
              System.Type.DefaultBinder,//获取对默认绑定器的引用,该绑定器实现用于选择的内部规则
              new Type[] { typeof(string),typeof(float)},//构造函数的两个参数形参类型
              new ParameterModifier[] { new ParameterModifier(2)});//为构造函数的结构 指定参数的个数
    
                //通过构造函数 获得实际对象
                var TestClass = constructor.Invoke(new object[] { "测试",2.2F});
    
                //获取所有 实例 私有 属性
                PropertyInfo[] propertyInfos = clazz.GetProperties(BindingFlags.Instance|BindingFlags.NonPublic);
    
                foreach (PropertyInfo propertyInfo in propertyInfos)
                {
                    Console.WriteLine("
    属性名:"+propertyInfo.Name+"属性值:"+propertyInfo.GetValue(TestClass)+"
    ");
                }
                //循环获取所获取属性的值
            }
            #endregion
    
        }
    }
    

      

  • 相关阅读:
    node.js 安装后怎么打开 node.js 命令框
    thinkPHP5 where多条件查询
    网站title中的图标
    第一次写博客
    Solution to copy paste not working in Remote Desktop
    The operation could not be completed. (Microsoft.Dynamics.BusinessConnectorNet)
    The package failed to load due to error 0xC0011008
    VS2013常用快捷键
    微软Dynamics AX的三层架构
    怎样在TFS(Team Foundation Server)中链接团队项目
  • 原文地址:https://www.cnblogs.com/JourneyOfFlower/p/10390844.html
Copyright © 2011-2022 走看看