详解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接口传参的一些方式方法,算是一个笔记,也希望能帮初学者少走弯路.本 ...
随机推荐
- app.json
APP.JSON 文件来对微信小程序进行全局配置,决定页面文件的路径.窗口表现.设置网络超时时间.设置多 TAB 等.相当于iOS开发中的AppDelegate 注意该文件不可添加任何注释. { ...
- 改Android手机定位位置
手机定位方法 1,gps等卫星定位,如美国的gps,欧洲的伽利略,中国的北斗等,通过至少三颗卫星,用三角定位和时间等算法,计算出设备的经纬度,到地图上找到这个经纬度的地名 2,移动运营商基站定位,通过 ...
- 上传图片JS插件Plupload
Plupload有以下功能和特点: 1.拥有多种上传方式:HTML5.flash.silverlight以及传统的<input type=”file” />.Plupload会自动侦测当前 ...
- 20155326 《Java程序设计》第8周学习总结
20155326 <Java程序设计>第8周学习总结 教材学习内容总结 NIO (1)NIO使用频道来衔接数据节点,在处理数据时,NIO可以让你设定缓冲区容量,在缓冲区中对感兴趣的数据区块 ...
- Establish a website in 5 minutes
$sudo apt-get update //update $sudo apt-get install tasksel ...
- activemq生产者和消费者的双向通信
http://websystique.com/spring/spring-4-jms-activemq-example-with-jmslistener-enablejms/
- Android-WebView与本地HTML (Java调用--->HTML的方法)
上一篇博客 Android-WebView与本地HTML (HTML调用-->Java的方法) 介绍了 JavaScript 调用--> Java中的方法,而此篇博客是介绍 Java 调用 ...
- 一步一步学习Swift之(三):巧用AutoLayout布局
一些初学者经常在使用autoLayout时,做得效果不太理想,经常会出现界面错乱的情况. 本文章用一个小实例说明autoLayout的使用 非常的简单,只要记住 规则就可以使界面适屏布局,适配各种ip ...
- 【BZOJ2589】 Spoj 10707 Count on a tree II
BZOJ2589 Spoj 10707 Count on a tree II Solution 吐槽:这道题目简直...丧心病狂 如果没有强制在线不就是树上莫队入门题? 如果加了强制在线怎么做? 考虑 ...
- js判断是否手机自动跳转移动端
写法一: {literal} <script> //判断是否手机自动跳转 var browser={versions:function(){var u=navigator.userAgen ...