.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("\r\n1.方法调用信息:\r\n①调用方法:{0}\r\n②传递参数:{1}", "Demo", param);
}
#endregion #region 用于测试反射执行公开静态方法(带有自定义方法成员特性)---> 成员2
[MethodAttribute("Demo1", "测试特性类示例方法Demo1")]
public static string Demo1(string param)
{
return string.Format("\r\n1.方法调用信息:\r\n①调用方法:{0}\r\n②传递参数:{1}", "Demo1", param);
}
#endregion public void ConsoleMsg(string strMsg)
{
Console.WriteLine("\r\nMsg:"+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_prj\AttributeTest\bin\Debug\AttributeTest.exe");
clazz3 = assembly.GetType("AttributeTest.TestClass"); //判别得到的反射是否一致
if (clazz.Equals(clazz2) && clazz2.Equals(clazz3))
Console.WriteLine("\r\nclazz==clazz1==clazz2==clazz3\r\n"); //直接利用 程序集和类的完全限定名 创建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("\r\n");
} #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("\r\n");
}
#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("\r\n2.输出当前方法特性信息:");
Console.WriteLine("①当前调用方法名称:[" + methodAttribute.MethodName + "]");
Console.WriteLine("②方法描述:[" + methodAttribute.MethodDesc + "]");
}
else
{
Console.WriteLine("\r\n当前传入的方法没有反射信息!\r\n");
}
} #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("\r\n字段:"+field.Name+",值:"+field.GetValue(TestClass).ToString()+"\r\n");
}
} #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("\r\n属性名:"+propertyInfo.Name+"属性值:"+propertyInfo.GetValue(TestClass)+"\r\n");
}
//循环获取所获取属性的值
}
#endregion }
}
.NET C#利用反射获取类文件以及其中的方法&属性 并获取类及方法上的特性的更多相关文章
- 脚本工具(获取某个文件夹下的所有图片属性批量生成css样式)
问题描述: 由于有一次工作原因,就是将某个文件夹下的所有图片,通过CSS描述他们的属性,用的时候就可以直接引用.但是我觉得那个文件夹下的图片太多,而且CSS文件的格式又有一定的规律,所有想通过脚本来生 ...
- IOS中获取各个文件的目录路径的方法和NSFileManager类
转自:http://blog.sina.com.cn/s/blog_5fb39f910101di92.html IOS中获取各种文件的目录路径的方法 iphone沙箱模型的有四个文件夹,分别是什么,永 ...
- java利用反射绕过私有检查机制实行对private、protected成员变量或方法的访问
在java中,如果类里面的变量是声明了private的,那么只能在被类中访问,外界不能调用,如果是protected类型的,只能在子类或本包中调用,俗话说没有不透风的墙.但是可以利用java中的反射从 ...
- python 获取当前文件夹路径及父级目录的几种方法
获取当前文件夹路径及父级目录: import os current_dir = os.path.abspath(os.path.dirname(__file__)) print(current_dir ...
- C# 如何利用反射来加载程序集,并调用程序集中有关类的方法【转】
假设在C盘根目录下有个Dog的Dll程序集文件,该程序集文件中包含类Dog 该类中有个狗叫几声的方法,如何通过反射来加载这个C:\Dog.dll,并且调用Dog类里面的Sound方法呢: public ...
- 【转】获取到元素的 offsetLeft 、offsetTop属性不正常的解决方法。
原地址:http://hi.baidu.com/huidust520/item/85da006981a6c635ad3e834e 我在工作中遇到个问题: 在ie7下和360浏览器下获取到的 offs ...
- css选择器四大类:基本、组合、属性、伪类
什么是选择器?选择器的作用是通过它可以找到元素,把css样式传递给元素!css选择器主要分为:基本选择器.属性选择器.组合选择器与伪类选择器四个大类! css基本选择器 基本选择器又分为:*通配符.标 ...
- JavaScript 获取HTML中的CSS样式的属性以及值的的方法。
<body> <div id="wow" style="font-size:10px; float:left"></div> ...
- 利用反射,批量启动WCF服务
对于WCF的宿主启动来说,有好多方法,单独启动也很简单,可以根据业务需要来自由选择(单独启动方法这里就不做解释) 对于业务服务比较多的时候,往往需要多个服务来承载系统,但是如果将服务启动单独写代码启动 ...
随机推荐
- 算法练习之二叉树的最大深度,二叉树的层次遍历 II
1.二叉树的最大深度 给定一个二叉树,找出其最大深度. 二叉树的深度为根节点到最远叶子节点的最长路径上的节点数. 说明: 叶子节点是指没有子节点的节点. 示例:给定二叉树 [3,9,20,null,n ...
- VS2013+OpenCV3.4.2编译
一.准备工作: (1)在OpenCV官网下载3.4.2版本(注意选择Win pack),https://opencv.org/releases.html. (2)下载Contrib模块,https:/ ...
- Appium元素定位难点:混合式的native+webview
现在大部分app都是混合式的native+webview,对应native上的元素通过uiautomatorviewer很容易定位到,webview上的元素就无法识别了. 1.认识识webview & ...
- 不借助其他任何软件防止QQ被盗的小技巧
分享一个小技巧(防止QQ被盗号): 在登录的时候前面加个0,点击登录,如果显示账号不存在,是因为你没有在添加或注册账号这儿登录,也就是切换账号.PC端也可以,如下图: ...
- 在 SQL 中 快速 批量 插入数据的方法
方法1:逐条执行,速度慢. INSERT INTO testimport (name, message) VALUES ('testname', 'jfksdfkdsfjksadljfkdsfjsdl ...
- Python 爬取陈都灵百度图片
Python 爬取陈都灵百度图片 标签(空格分隔): 随笔 今天意外发现了自己以前写的一篇爬虫脚本,爬取的是我的女神陈都灵,尝试运行了一下发现居然还能用.故把脚本贴出来分享一下. import req ...
- Spring Cloud Zuul源码
一.Zuul源码分析(初始化流程.请求处理流程)
- 微软.NET CORE 3.0 预览版 7 发布:大幅减少 SDK 空间大小
据悉,这个预览版是 .Net Core 3 中重要的版本,可以视为原计划在 7 月发布的 RC 版本 (引自微软 .NET Core 首席 Program Manager Richard 先生原话), ...
- Linux sftp命令
sftp是Secure File Transfer Protocol的缩写,安全文件传送协议.可以为传输文件提供一种安全的网络的加密方法.sftp 与 ftp 有着几乎一样的语法和功能.SFTP 为 ...
- 7 批量查询mget、批量修改bulk
注意:当执行多条数据查询.增删改时,一定要用mget.bulk,提升性能,减少网络传输 mget 回顾:查询单个文档 GET /beauties/my/2 mget 查询多个文档: 不同 ...