详解C#特性和反射(二)
使用反射(Reflection)使得程序在运行过程中可以动态的获取对象或类型的类型信息,然后调用该类型的方法和构造函数,或访问和修改该类型的字段和属性;可以通过晚期绑定技术动态的创建类型的实例;可以获取程序集中的所有类型信息;可以在动态构建新类型;还可以检索元素所添加的特性;
※反射相关的类基本都位于命名空间System.Reflection中;
※动态构建新类型的类位于命名空间System.Reflection.Emit中;
一、访问或修改类型的实例、静态字段:
public class MyClass
{
public int myField;
public static int myStaticField;
} //使用方式:
//访问或修改类型的实例字段myField
MyClass myObj = new MyClass() { myField = }; //创建实例
Type myType = typeof(MyClass); //获取类型,或myObj.GetType()
FieldInfo fieldInfo = myType.GetField("myField"); //获取类型中指定的字段信息
Console.WriteLine((int)fieldInfo.GetValue(myObj)); //1,获取实例字段的值
fieldInfo.SetValue(myObj, ); //给实例字段赋值
//访问或修改类型的静态字段myStaticField
FieldInfo staticFieldInfo = myType.GetField("myStaticField"); //获取类型中指定的字段信息
Console.WriteLine(staticFieldInfo.GetValue(null)); //0,获取静态字段的值
staticFieldInfo.SetValue(null, ); //给静态字段赋值
※与直接赋值相比,使用反射赋值用时约长75倍,使用以下代码多次测试:
public class MyClass
{
public int myField;
} class Program
{
static void Main(string[] args)
{
Stopwatch stopwatch = new Stopwatch();
MyClass myObj = new MyClass() { myField = };
Type myType = typeof(MyClass);
FieldInfo fieldInfo = myType.GetField("myField"); stopwatch.Start();
for (int i = ; i < 10_000_000; i++)
{
fieldInfo.SetValue(myObj, );
}
stopwatch.Stop();
Console.WriteLine($"使用反射赋值1千万次耗时:{stopwatch.ElapsedMilliseconds}"); stopwatch.Reset();
stopwatch.Start();
for (int i = ; i < 10_000_000; i++)
{
myObj.myField = ;
}
stopwatch.Stop();
Console.WriteLine($"直接赋值1千万次耗时:{stopwatch.ElapsedMilliseconds}");
Console.Read();
}
}
二、访问或修改类型的实例、静态属性:
public class MyClass
{
public int MyProperty { get; set; }
public static int MyStaticProperty { get; set; }
}
//使用方式:
//访问或修改类型的实例属性MyProperty
MyClass myObj = new MyClass() { MyProperty = }; //创建实例
Type myType = typeof(MyClass); //获取类型,或myObj.GetType()
PropertyInfo propertyInfo = myType.GetProperty("MyProperty"); //获取类型中指定的属性信息
Console.WriteLine((int)propertyInfo.GetValue(myObj, null)); //1,获取实例属性的值
propertyInfo.SetValue(myObj, , null); //给实例属性赋值 //访问或修改类型的静态属性MyStaticProperty
PropertyInfo staticPropertyInfo = myType.GetProperty("MyStaticProperty"); //获取类型中指定的属性信息
Console.WriteLine(staticPropertyInfo.GetValue(null, null)); //0,获取静态属性的值
staticPropertyInfo.SetValue(null, ); //给静态属性赋值
※在使用反射给属性赋值时,如果该属性不具有set访问器,则会抛出异常ArgumentException;
三、调用类型的方法:
public class MyClass
{
public void MyFunc(int num)
{
Console.WriteLine("MyFunc(int num) execute, the parameter is: " + num);
}
public static void MyStaticFunc(int num)
{
Console.WriteLine("MyStaticFunc(int num) execute, the parameter is: " + num);
}
}
//使用方式:
//调用类型的实例方法MyFunc
MyClass myObj = new MyClass(); //创建实例
Type myType = typeof(MyClass); //获取类型,或myObj.GetType()
MethodInfo methodInfo = myType.GetMethod("MyFunc"); //获取类型中指定的方法信息
methodInfo.Invoke(myObj, new object[] { }); //调用实例方法,并传入参数,无参传null
//MyFunc(int num) execute, the parameter is: 10 //调用类型的实例方法MyStaticFunc
MethodInfo staticMethodInfo = myType.GetMethod("MyStaticFunc"); //获取类型中指定的方法信息
staticMethodInfo.Invoke(null, new object[] { }); //调用静态方法,并传入参数,无参传null
//MyStaticFunc(int num) execute, the parameter is: 20
四、调用类型的构造函数同时创建实例:
public class MyClass
{
public MyClass()
{
Console.WriteLine("MyClass() execute.");
}
public MyClass(int num)
{
Console.WriteLine("MyClass(int num) execute, the parameter is: " + num);
}
}
//使用方式:
//调用无参的构造函数
Type myType = typeof(MyClass); //获取类型,或myObj.GetType()
ConstructorInfo constructorInfo = myType.GetConstructor(new Type[] { }); //获取类型中指定的构造函数信息,传入该构造函数的参数列表的类型数组,无参传空数组
MyClass myObj = constructorInfo.Invoke(null) as MyClass; //通过调用构造函数创建实例,无参传null
//MyClass() execute. //调用带参数的构造函数
constructorInfo = myType.GetConstructor(new Type[] { typeof(int) }); //获取类型中指定的构造函数信息,传入该构造函数的参数列表的类型数组
myObj = constructorInfo.Invoke(new object[] { }) as MyClass; //通过调用构造函数创建实例,并传入参数
//MyClass(int num) execute, the parameter is: 20
※也可以使用Type类中的实例方法InvokeMember()来调用指定成员;
五、使用反射查找特性:
1.如果元素使用了特性,在没有检索并对其进行操作前该特性没有任何价值,可以使用反射在程序运行过程中获取元素添加的特性然后对其进行操作,使用特性基类Attribute中的静态方法GetCustomAttributes(MemberInfo element)或命名空间System.Reflection中的扩展方法GetCustomAttributes(this MemberInfo element)来获取类型或成员的所有特性信息:
Attribute[] attributes = Attribute.GetCustomAttributes(typeof(MyClass));
//IEnumerable<Attribute> attributes = typeof(MyClass).GetCustomAttributes();
foreach (var item in attributes)
{
if (item is MyselfAttribute)
{
MyselfAttribute attribute = item as MyselfAttribute;
Console.WriteLine(attribute .ClassName + " " + attribute .Author); //MyClass Me
}
}
2.这两个方法都有对应的重载方法,可以传入要检索的指定特性的类型,这样即可得到元素中所有指定类型的特性信息:
Attribute[] attributes = Attribute.GetCustomAttributes(typeof(MyClass), typeof(MyselfAttribute));
//IEnumerable<Attribute> attributes = typeof(MyClass).GetCustomAttributes(typeof(MyselfAttribute));
foreach (var item in attributes)
{
MyselfAttribute attribute = item as MyselfAttribute;
Console.WriteLine(attribute.ClassName + " " + attribute.Author); //MyClass Me
}
※如果未找到任何特性或指定类型的特性,这些方法会返回一个空数组;
3.也可以使用基类Attribute中的静态方法GetCustomAttribute(MemberInfo element, Type attributeType)或命名空间System.Reflection中的扩展方法GetCustomAttribute(this MemberInfo element, Type attributeType)来获取类型或成员的指定特性信息;
※如果未找到指定类型的特性,会返回null;
※在检索的元素中存在多个相同的指定类型的特性时,会抛出异常Reflection.AmbiguousMatchException;
类型信息、晚期绑定、动态创建类型等会在下一篇中介绍。
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的认可是我写作的最大动力!
作者:Minotauros
出处:https://www.cnblogs.com/minotauros/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
详解C#特性和反射(二)的更多相关文章
- 详解C#泛型(二) 获取C#中方法的执行时间及其代码注入 详解C#泛型(一) 详解C#委托和事件(二) 详解C#特性和反射(四) 记一次.net core调用SOAP接口遇到的问题 C# WebRequest.Create 锚点“#”字符问题 根据内容来产生一个二维码
详解C#泛型(二) 一.自定义泛型方法(Generic Method),将类型参数用作参数列表或返回值的类型: void MyFunc<T>() //声明具有一个类型参数的泛型方法 { ...
- EF+LINQ事物处理 C# 使用NLog记录日志入门操作 ASP.NET MVC多语言 仿微软网站效果(转) 详解C#特性和反射(一) c# API接受图片文件以Base64格式上传图片 .NET读取json数据并绑定到对象
EF+LINQ事物处理 在使用EF的情况下,怎么进行事务的处理,来减少数据操作时的失误,比如重复插入数据等等这些问题,这都是经常会遇到的一些问题 但是如果是我有多个站点,然后存在同类型的角色去操作 ...
- 详解C#特性和反射(四)
本篇内容是特性和反射的最后一篇内容,前面三篇文章: 详解C#特性和反射(一) 详解C#特性和反射(二) 详解C#特性和反射(三) 一.晚期绑定(Late Binding)是一种在编译时不知道类型及其成 ...
- 详解C#特性和反射(一)
使用特性(Attribute)可以将描述程序集的信息和描述程序集中任何类型和成员的信息添加到程序集的元数据和IL代码中,程序可以在运行时通过反射获取到这些信息: 一.通过直接或间接的继承自抽象类Sys ...
- 详解C#特性和反射(三)
类型信息(Type Information)用来表示类型声明的信息,通过抽象基类System.Type的实例存储这些信息,当使用反射时,CLR获取指定类型的Type对象,通过这个对象即可访问该类型的任 ...
- 【转】详解C#中的反射
原帖链接点这里:详解C#中的反射 反射(Reflection) 2008年01月02日 星期三 11:21 两个现实中的例子: 1.B超:大家体检的时候大概都做过B超吧,B超可以透过肚皮探测到你内 ...
- 详解Java8特性之新的日期时间 API
详解Java8特性之新的日期时间 API http://blog.csdn.net/timheath/article/details/71326329 Java8中时间日期库的20个常用使用示例 ht ...
- Git使用总结 Asp.net生命周期与Http协议 托管代码与非托管代码的区别 通过IEnumerable接口遍历数据 依赖注入与控制反转 C#多线程——优先级 AutoFac容器初步 C#特性详解 C#特性详解 WPF 可触摸移动的ScrollViewer控件 .NET(C#)能开发出什么样的APP?盘点那些通过Smobiler开发的移动应用
一,原理 首先,我们要明白Git是什么,它是一个管理工具或软件,用来管理什么的呢?当然是在软件开发过程中管理软件或者文件的不同版本的工具,一些作家也可以用这个管理自己创作的文本文件,由Linus开发的 ...
- WebApi接口传参不再困惑(4):传参详解 一、get请求 二、post请求 三、put请求 四、delete请求 五、总结
前言:还记得刚使用WebApi那会儿,被它的传参机制折腾了好久,查阅了半天资料.如今,使用WebApi也有段时间了,今天就记录下API接口传参的一些方式方法,算是一个笔记,也希望能帮初学者少走弯路.本 ...
随机推荐
- HDU2732一个让我debug了一晚上的题目
思路都理解了,清晰了,就是代码不对,还是有些小地方自己注意不到,即使就在你的眼前也不易发现的那种 Description: 也是一个最大流的构图,没相出来,或者说想简单了也是标记点1 至 n * m是 ...
- java基础知识-原码,反码,补码
1.正数:原码,反码,补码:都一样. 2.负数:和正数的储存方式不同,负数都是以补码形式存储的. <1>负数的补码 把负数的原码除了符号位取反后再+1. <2>负数的原码 把对 ...
- CSS 基础 例子 背景色 & 背景图片
背景简写形式 : body {background:#ffffff url('img_tree.png') no-repeat right top;} 一.背景色 background-color ...
- 《principal component analysis based cataract grading and classification》学习笔记
Abstract A cataract is lens opacification caused by protein denaturation which leads to a decrease i ...
- .net图表之ECharts随笔06-这才是最简单的
今天搞柱形图的时候,发现了一个更简单的用法.那就是直接使用带all的那个js文件 基本步骤: 1.为ECharts准备一个具备大小(宽高)的Dom 2.ECharts的js文件引入(echarts-a ...
- [UWP开发] 在低版本中使用亚克力刷以及部分高版本控件
写于2018.10.3 仅在我的PC(17763)和WP(Limia 950 XL 15254)上测试过 微软在build 16299中引入了亚克力刷,但是Win10m并没有活那么久,lumia手机在 ...
- 【BZOJ3545】 [ONTAK2010]Peaks
BZOJ3545 [ONTAK2010]Peaks Solution 既然会加强版,直接把强制在线的操作去掉就好了. 代码实现 #include<stdio.h> #include< ...
- 201621123018《Java程序设计》第10周学习报告
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常相关内容. 2. 书面作业 本次PTA作业题集异常 1. 常用异常 1.1 自己以前编写的代码中经常出现什么异常.需要捕获吗(为 ...
- jzoj4229
按照題意暴力模擬即可 #include<bits/stdc++.h> using namespace std; int m; typedef long long ll; ll a1,q,n ...
- mysql日期时间函数使用总结
获取函数 mysql默认的时间格式: yyyy-MM-dd 或者 yyyy-MM-dd HH:mm:ss 1. Date() 返回日期部分, date('2018-02-14 17:03:04') ...