详解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接口传参的一些方式方法,算是一个笔记,也希望能帮初学者少走弯路.本 ...
随机推荐
- 动态创建控件 #Create(...)
在类中创建一个控件对象;例:CButton m_btn; 用Create创建一个对象(#其实已经与其绑定)m_btn.Create(.....); #注意Create()函数的参数 问题一:点击一个b ...
- js五道经典练习题--第二道仿qq聊天框
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>& ...
- [jquery]如何实现页面单块DIV区域滚动展示
// 未实现功能的代码 1(自己写的代码) var _cur_top = $(window).scrollTop(); var num = $(".class_section"). ...
- ios调用系统界面显示英文
调用系统相册界面 UIImagePickerController *picker = [[UIImagePickerController alloc] init]; picker.sourceType ...
- linux中yum命令的解析
yum(全称为 Yellow dog Updater, Modified)是一个在Fedora和RedHat以及SUSE中的Shell前端软件包管理器.基於RPM包管理,能够从指定的服务器自动下载RP ...
- matlab 中fft的用法
一.调用方法X=FFT(x):X=FFT(x,N):x=IFFT(X);x=IFFT(X,N) 用MATLAB进行谱分析时注意: (1)函数FFT返回值的数据结构具有对称性. 例:N=8;n=0:N- ...
- C#通过字符串名称来调用对应字符串名称的方法
前段时间在一个项目中,在一个地方要将函数所在类中的方法都调用一遍,但是否调用要通过配置文件中的内容决定.所以为了减少代码量,在网上查了相关信息,终于成功的将其应用到了项目中,我在这里将我做的一个简单例 ...
- .Net桌面程序自动更新NAppUpdate
自动更新介绍 我们做了程序,不免会有版本升级,这就需要程序有自动版本升级的功能.应用程序自动更新是由客户端应用程序自身负责从一个已知服务器下载并安装更新,用户唯一需要进行干预的是决定是否愿意现在或以后 ...
- 【BZOJ3280】 小R的烦恼(费用流,建模)
有很浓厚的熟悉感?餐巾计划问题? 不就是多了几个医院,相当于快洗部和慢洗部开了分店. 考虑建图: 如果把每一天拆成两个点,一个表示需求,另一个表示拥有的话. 显然就是一个两边的图,考虑如果我现在有人, ...
- 564. Find the Closest Palindrome
Given an integer n, find the closest integer (not including itself), which is a palindrome. The 'clo ...