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

  1. using System;
  2.  
  3. namespace AttributeTest
  4. {
  5. /* 特性说明
  6. 特性本质是一个继承和使用了系统基类的"类",用以将元数据或声明信息与代码(程序集、类型、方法、属性等)相关联。特性与程序实体关联后,
  7. 即可在运行时使用名为“反射”的技术查询特性。
  8. 官方介绍的很详细,我们就一起来了解一下它的用法。
  9.  
  10. 特性具有以下属性:
  11.  
  12. 1.特性可向程序中添加元数据。元数据是有关在程序中定义的类型的信息。所有的.NET 程序集都包含指定的一组元数据,
  13. 这些元数据描述在程序集中定义的类型和类型成员。可以添加自定义特性,以指定所需的任何附加信息。
  14.  
  15. 2.可以将一个或多个特性应用到整个程序集、模块或较小的程序元素(如类和属性)。
  16.  
  17. 3.特性可以与方法和属性相同的方式接受参数。
  18.  
  19. 4.程序可以使用反射检查自己的元数据或其他程序内的元数据。
  20. */
  21.  
  22. #region 声明一个 作用于成员方法 的特性
  23. //1.第一步 继承自定义属性的基类 Attribute
  24. //2.第二步 指定 我们自定义特性类 的一些属性,用系系统特性指定
  25. // AttributeTargets:指定为程序中的何种成员设置属性 可写多个 例: AttributeTargets.Class|AttributeTargets.Method
  26. // AllowMultiple:如果允许为一个实例多次指定该特性,则为 true;否则为 false。默认为 false。
  27. // Inherited:如果该属性可由派生类和重写成员继承,则为 true,否则为 false。默认为 true。
  28. [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
  29. public class MethodAttribute : Attribute
  30. {
  31. /// <summary>
  32. /// 方法名称
  33. /// </summary>
  34. public string MethodName { set; get; }
  35. /// <summary>
  36. /// 方法描述
  37. /// </summary>
  38. public string MethodDesc { set; get; }
  39.  
  40. /// <summary>
  41. /// 方法描述特性
  42. /// </summary>
  43. /// <param name="methodName">方法名称</param>
  44. /// <param name="methodDescription">方法描述</param>
  45. public MethodAttribute(string methodName, string methodDescription)
  46. {
  47. MethodName = methodName;
  48. MethodDesc = methodDescription;
  49. }
  50. }
  51. #endregion
  52.  
  53. #region 声明一个 作用于类 的特性
  54. [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]//第一步
  55. public class ClassAttribute : Attribute//第二步
  56. {
  57. string ClassName { set; get; }
  58. string ClassDesc { set; get; }
  59.  
  60. public ClassAttribute(string className, string classDesc)
  61. {
  62. ClassName = className;
  63. ClassDesc = classDesc;
  64. }
  65.  
  66. //重写当前特性的ToString()方法
  67. public override string ToString()
  68. {
  69. return string.Format(@"当前类特性名:[ClassAttribute]
  70. 特性成员1:ClassName-->值:{0},
  71. 特性成员2:ClassDesc-->值:{1}", ClassName, ClassDesc);
  72. }
  73. }
  74. #endregion
  75. }

  

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

  1. using System;
  2.  
  3. namespace AttributeTest
  4. {
  5. #region 为一个类编写成员 并使用自定义的类特性以及成员特性
  6. [ClassAttribute("TestClass", "测试反射及特性")]
  7. class TestClass
  8. {
  9. string _StrTest = "测试信息";
  10. float _Version = 1.1F;
  11. float Version { set { _Version = value; } get { return _Version; } }
  12. string StrTest { set { _StrTest = value; } get { return _StrTest; } }
  13.  
  14. public TestClass()
  15. {
  16.  
  17. }
  18.  
  19. TestClass(string strTest,float version)
  20. {
  21. StrTest = strTest;
  22. Version = version;
  23. }
  24.  
  25. #region 用于测试反射执行私有非静态方法(带有自定义方法成员特性)---> 成员1
  26. [MethodAttribute("Demo", "测试特性类示例方法Demo")]
  27. string Demo(string param)
  28. {
  29. return string.Format("\r\n1.方法调用信息:\r\n①调用方法:{0}\r\n②传递参数:{1}", "Demo", param);
  30. }
  31. #endregion
  32.  
  33. #region 用于测试反射执行公开静态方法(带有自定义方法成员特性)---> 成员2
  34. [MethodAttribute("Demo1", "测试特性类示例方法Demo1")]
  35. public static string Demo1(string param)
  36. {
  37. return string.Format("\r\n1.方法调用信息:\r\n①调用方法:{0}\r\n②传递参数:{1}", "Demo1", param);
  38. }
  39. #endregion
  40.  
  41. public void ConsoleMsg(string strMsg)
  42. {
  43. Console.WriteLine("\r\nMsg:"+strMsg);
  44. }
  45. }
  46. #endregion
  47.  
  48. }

 

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

  1. using System;
  2. using System.Reflection;
  3.  
  4. namespace AttributeTest
  5. {
  6. class Program
  7. {
  8. #region 存储 TestClass类反射信息 的字段
  9. static Type clazz;
  10. static Type clazz1;
  11. static Type clazz2;
  12. static Type clazz3;
  13. #endregion
  14.  
  15. static void Main(string[] args)
  16. {
  17. Program program = new Program();
  18. program.GetReflectInfoByClass(); //得到TestClass类的反射
  19. program.ReflectInvokePrivateNonStaticMethod();//反射的方式调用TestClass类中私有非静态方法 并输出其方法上的特性
  20. program.ReflectInvokePublicStaticMethod(); //反射的方式调用TestClass类中公开静态方法 并输出其方法上的特性
  21. program.GetAllField(); //获取TestClass类中的 字段
  22. program.GetAllProp(); //获取TestClass类中的 属性
  23. program.ReflectGetAttributeByClass(); //获取TestClass类上的 特性
  24.  
  25. Console.ReadKey();
  26. }
  27.  
  28. #region 通过【类名】和【类的限定名】和 【程序集(Assembly)】取得类的【反射信息】
  29. //通过类名和类的限定名取得类的反射信息
  30. void GetReflectInfoByClass()
  31. {
  32. //以下三种种方式得到当前类的反射信息 得到的结果都一样
  33.  
  34. //1.通过TestClass类名得到类反射信息
  35. clazz = typeof(TestClass);
  36. clazz1 = new TestClass().GetType();
  37.  
  38. //2.通过TestClass类的限定名得到其反射信息
  39. clazz2 = Type.GetType("AttributeTest.TestClass");
  40.  
  41. //3.通过【程序集.dll】或【可执行文件.exe】反射TestClass
  42. Assembly assembly = Assembly.LoadFile(@"F:\Projects_C#\UpLoadData_prj\AttributeTest\bin\Debug\AttributeTest.exe");
  43. clazz3 = assembly.GetType("AttributeTest.TestClass");
  44.  
  45. //判别得到的反射是否一致
  46. if (clazz.Equals(clazz2) && clazz2.Equals(clazz3))
  47. Console.WriteLine("\r\nclazz==clazz1==clazz2==clazz3\r\n");
  48.  
  49. //直接利用 程序集和类的完全限定名 创建TestClass对象 调其方法
  50. var obj = assembly.CreateInstance("AttributeTest.TestClass");
  51. if (obj is TestClass)
  52. {
  53. TestClass tc = obj as TestClass;
  54. tc.ConsoleMsg("反射会破坏访问权限");
  55. }
  56. }
  57. #endregion
  58.  
  59. #region 用反射的方式调用【TestClass类】私有非静态方法
  60. /// <summary>
  61. /// 用反射的方式调用TestClass类中私有非静态方法
  62. /// </summary>
  63. void ReflectInvokePrivateNonStaticMethod()
  64. {
  65. //Demo为私有方法 指定在类中搜索私有成员|实例成员
  66. BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Instance;
  67.  
  68. //反射私有方法需要指定 BindingFlags.NonPublic
  69. var Demo = clazz1.GetMethod("Demo", bindingFlags);//私有非静态
  70.  
  71. #region 调用私有非静态方法[Demo]
  72. //1.实例化[Demo]方法所在类, 第二个参数默认false:不可访问私有构造函数 true:则可访问类中私有构造函数
  73. object o = Activator.CreateInstance(clazz2, true);
  74.  
  75. //2.通过类的实例调用方法[Demo] (含一个参数)
  76. var returns = Demo.Invoke(o, new object[] { "ReflectionTest" });
  77. Console.Write(returns);
  78. #endregion
  79.  
  80. //输出方法上的特性信息
  81. ReflectGetAttributeByMethod(Demo);
  82. Console.Write("\r\n");
  83. }
  84.  
  85. #endregion
  86.  
  87. #region 用反射的方式调用【TestClass类】中公开静态方法
  88. /// <summary>
  89. /// 用反射的方式调用TestClass类中公开静态方法
  90. /// </summary>
  91. void ReflectInvokePublicStaticMethod()
  92. {
  93. #region 调用公开静态方法
  94. //1.Demo1为公开访问权限,BindingFlags默认为 Instance、Public
  95. var Demo1 = clazz2.GetMethod("Demo1");
  96.  
  97. //2.Demo1为静态方法 调用不需要实例化其所在类
  98. var returns = Demo1.Invoke(clazz, new object[] { "ReflectionTest1" });
  99.  
  100. //输出方法返回值
  101. Console.Write(returns);
  102. #endregion
  103.  
  104. //通过反射信息得到方法上的特性信息
  105. ReflectGetAttributeByMethod(Demo1);
  106. Console.WriteLine("\r\n");
  107. }
  108. #endregion
  109.  
  110. #region 通过 【方法反射信息】 得到方法使用的特性
  111. /// <summary>
  112. /// 通过方法的反射信息得到方法使用的特性
  113. /// </summary>
  114. /// <param name="method"></param>
  115. void ReflectGetAttributeByMethod(dynamic method)
  116. {
  117. if (method == null)
  118. {
  119. Console.WriteLine("参数不能为空!,按任意键结束!");
  120. Console.ReadKey();
  121. return;
  122. }
  123.  
  124. //得到当前方法上的特性类 信息
  125. MethodAttribute methodAttribute = Attribute.GetCustomAttribute(method, typeof(MethodAttribute));
  126. if (methodAttribute != null)
  127. {
  128. Console.WriteLine("\r\n2.输出当前方法特性信息:");
  129. Console.WriteLine("①当前调用方法名称:[" + methodAttribute.MethodName + "]");
  130. Console.WriteLine("②方法描述:[" + methodAttribute.MethodDesc + "]");
  131. }
  132. else
  133. {
  134. Console.WriteLine("\r\n当前传入的方法没有反射信息!\r\n");
  135. }
  136. }
  137.  
  138. #endregion
  139.  
  140. #region 获取【类】的 特性 信息
  141. /// <summary>
  142. /// 获取修饰类的 特性 信息
  143. /// </summary>
  144. void ReflectGetAttributeByClass()
  145. {
  146. Attribute attribute = Attribute.GetCustomAttribute(clazz2, typeof(Attribute));
  147. if (attribute != null)
  148. {
  149. Console.WriteLine(attribute.ToString());
  150. }
  151. }
  152. #endregion
  153.  
  154. #region 获取【字段】并得其值
  155. //获取字段并得到字段的值
  156. void GetAllField()
  157. {
  158. //获取构造函数 公开无参的构造方法
  159. var constructor = clazz.GetConstructor(new Type[0]);
  160.  
  161. //通过构造函数的调用获取对象
  162. var TestClass = constructor.Invoke(new object[0]);
  163.  
  164. //获取所 实例 私有 字段
  165. FieldInfo[] fields = clazz.GetFields(BindingFlags.Instance|BindingFlags.NonPublic);
  166.  
  167. //循环遍历字段和其值
  168. foreach (FieldInfo field in fields)
  169. {
  170. Console.WriteLine("\r\n字段:"+field.Name+",值:"+field.GetValue(TestClass).ToString()+"\r\n");
  171. }
  172. }
  173.  
  174. #endregion
  175.  
  176. #region 获取【属性】并得其值
  177. //获取属性并得到属性的值
  178. void GetAllProp()
  179. {
  180. //获取有两个参数私有非静态的构造方法
  181. var constructor = clazz.GetConstructor(
  182.           BindingFlags.Instance|BindingFlags.NonPublic,//方法修饰符
  183.           System.Type.DefaultBinder,//获取对默认绑定器的引用,该绑定器实现用于选择的内部规则
  184.           new Type[] { typeof(string),typeof(float)},//构造函数的两个参数形参类型
  185.           new ParameterModifier[] { new ParameterModifier(2)});//为构造函数的结构 指定参数的个数
  186.  
  187. //通过构造函数 获得实际对象
  188. var TestClass = constructor.Invoke(new object[] { "测试",2.2F});
  189.  
  190. //获取所有 实例 私有 属性
  191. PropertyInfo[] propertyInfos = clazz.GetProperties(BindingFlags.Instance|BindingFlags.NonPublic);
  192.  
  193. foreach (PropertyInfo propertyInfo in propertyInfos)
  194. {
  195. Console.WriteLine("\r\n属性名:"+propertyInfo.Name+"属性值:"+propertyInfo.GetValue(TestClass)+"\r\n");
  196. }
  197. //循环获取所获取属性的值
  198. }
  199. #endregion
  200.  
  201. }
  202. }

  

.NET C#利用反射获取类文件以及其中的方法&属性 并获取类及方法上的特性的更多相关文章

  1. 脚本工具(获取某个文件夹下的所有图片属性批量生成css样式)

    问题描述: 由于有一次工作原因,就是将某个文件夹下的所有图片,通过CSS描述他们的属性,用的时候就可以直接引用.但是我觉得那个文件夹下的图片太多,而且CSS文件的格式又有一定的规律,所有想通过脚本来生 ...

  2. IOS中获取各个文件的目录路径的方法和NSFileManager类

    转自:http://blog.sina.com.cn/s/blog_5fb39f910101di92.html IOS中获取各种文件的目录路径的方法 iphone沙箱模型的有四个文件夹,分别是什么,永 ...

  3. java利用反射绕过私有检查机制实行对private、protected成员变量或方法的访问

    在java中,如果类里面的变量是声明了private的,那么只能在被类中访问,外界不能调用,如果是protected类型的,只能在子类或本包中调用,俗话说没有不透风的墙.但是可以利用java中的反射从 ...

  4. python 获取当前文件夹路径及父级目录的几种方法

    获取当前文件夹路径及父级目录: import os current_dir = os.path.abspath(os.path.dirname(__file__)) print(current_dir ...

  5. C# 如何利用反射来加载程序集,并调用程序集中有关类的方法【转】

    假设在C盘根目录下有个Dog的Dll程序集文件,该程序集文件中包含类Dog 该类中有个狗叫几声的方法,如何通过反射来加载这个C:\Dog.dll,并且调用Dog类里面的Sound方法呢: public ...

  6. 【转】获取到元素的 offsetLeft 、offsetTop属性不正常的解决方法。

    原地址:http://hi.baidu.com/huidust520/item/85da006981a6c635ad3e834e 我在工作中遇到个问题: 在ie7下和360浏览器下获取到的  offs ...

  7. css选择器四大类:基本、组合、属性、伪类

    什么是选择器?选择器的作用是通过它可以找到元素,把css样式传递给元素!css选择器主要分为:基本选择器.属性选择器.组合选择器与伪类选择器四个大类! css基本选择器 基本选择器又分为:*通配符.标 ...

  8. JavaScript 获取HTML中的CSS样式的属性以及值的的方法。

    <body> <div id="wow" style="font-size:10px; float:left"></div> ...

  9. 利用反射,批量启动WCF服务

    对于WCF的宿主启动来说,有好多方法,单独启动也很简单,可以根据业务需要来自由选择(单独启动方法这里就不做解释) 对于业务服务比较多的时候,往往需要多个服务来承载系统,但是如果将服务启动单独写代码启动 ...

随机推荐

  1. 运行报错:'_TestResult' object has no attribute 'outputBuffer'

    一.运行main函数,未生成测试报告,报错:'_TestResult' object has no attribute 'outputBuffer' 解决方式: 1.在HTMLTestReportCN ...

  2. LeetCode 201. 数字范围按位与(Bitwise AND of Numbers Range)

    201. 数字范围按位与 201. Bitwise AND of Numbers Range 题目描述 给定范围 [m, n],其中 0 <= m <= n <= 214748364 ...

  3. [转帖]JAVA BIO与NIO、AIO的区别(这个容易理解)

    JAVA BIO与NIO.AIO的区别(这个容易理解) https://blog.csdn.net/ty497122758/article/details/78979302 2018-01-05 11 ...

  4. 长乐培训Day4

    T1 矩阵 题目 [题目描述] 从前有个 n×m 的矩阵,初始时每个位置均为 0.你需要依次执行 q 个操作,每个操作会指定一行或一列,然后将该行或该列的所有元素全部赋为一个相同的值. 输出操作完成后 ...

  5. Docker入门以及常用命令

    目的: Docker入门 Docker简介 Centos7安装Docker Docker HelloWorld运行原理解析 阿里云镜像仓库配置 Docker常用命令 Docker基本命令 Docker ...

  6. 全栈项目|小书架|服务器开发-Koa2中间件机制洋葱模型了解一下

    KOA2 是什么? Koa是一个新的 web 框架,由 Express 幕后的原班人马打造, 致力于成为 web 应用和 API 开发领域中的一个更小.更富有表现力.更健壮的基石. 通过利用 asyn ...

  7. (三) Docker 常用操作与CentOS7 防火墙命令

    参考并感谢 Docker 常用命令 https://docs.docker.com/engine/reference/commandline/docker/ Docker 登录docker账户 doc ...

  8. Socket HttpListen

    HttpListener sSocket = new HttpListener(); sSocket.Prefixes.Add("http://127.0.0.1:8080/"); ...

  9. Selenium与PhantomJS踩过的坑

    Selenium与PhantomJS踩过的坑 Selenium Selenium是一个Web的自动化测试工具,最初是为网站自动化测试而开发的,类型像我们玩游戏用的按键精灵,可以按指定的命令自动化操作, ...

  10. semaphore demo 并行 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

    import 'dart:async'; import 'package:semaphore/semaphore.dart'; import 'dart:io'; import 'dart:conve ...