C#反射的基本应用
反射描述了在运行过程中检查和处理程序元素的功能。反射可以完成以下任务:
- 枚举类型的成员;
- 实例化新对象;
- 执行对象的成员;
- 查找类型的信息;
- 查询程序集的信息;
- 检查应用于某种类型的自定义特性;
- 创建和编译新程序集。
1、Type类
Type类是一个抽象的基类。只要实例化一个Type对象,实际上就是实例化了Type的一个派生类。获取给定类型的Type引用三种方式:
- 使用c#的typeof运算符。其参数是类型的名称(不放在引号中);
- 使用GetType()方法,所有的类都是继承自Object类(值类型实际上也是如此),其具有该方法。
- 调用Type类的静态方法GetType():Type t=Type.GetType("System.Double")。
1.1、Type的属性
Type的属性可以分为三类。首先,许多属性都可以获取包含与类相关的各种名称的字符串。
- Name:数据类型名
- FullName:数据类型的完全限定名(包括命名空间名)
- Namespace:在其中定义数据类型的名称空间名
其次,属性能获取Type对象的引用。
- BaseType:该Type的直接基本类型
- UnderlyingSystemType:该Type在.net运行库中映射到类型(某些.net基类实际上映射到由IL识别的特定预定义类型)
最后,许多布尔类型属性表示这种类型是一个类,还是一个枚举等。这些属性包含:IsAbstract、IsArray、IsClass、IsEnum、IsInterface、IsPointer、IsPrimitive(一种预定义的基本数据类型)、IsPublic、IsSealed和IsValueType等。
1.2、Type的方法
Type的大多数方法都用于获取对应数据类型的成员信息:构造函数、属性、方法和事件等。它的许多方法都具有想同的模式。
- GetConstrucotr(), GetConstrucotrs():获取ConstrucotrInfo对象类型;
- GetEvent(), GetEvents():获取EventInfo对象类型;
- GetField(), GetFields():获取FieldInfo对象类型;
- GetMember(), GetMembers(), GetDefaultMembers():获取MemberInfo对象类型;
- GetMethod(), GetMethods():获取MethodInfo对象类型;
- GetProperty(), GetProperties(): 获取PropertyInfo对象类型。
GetMember()和GetMembers()方法返回数据类型的任何成员或所有成员的详细信息,不管这些成员是构造函数、属性或方法等。
2、Assembly类
Assembly类允许访问给定程序集的元素据,可以加载和执行程序集的方法等。使用Assembly实例之前需要加载对应的程序集到正在运行的进程中。使用静态成员Assembly.Load()或Assembly.LoadFrom(),Load()方法的参数是程序集的名称,运行库会在哥哥位置上搜索该程序集,位置包括本地目录和全局程序集缓存。LoadFrom()方法参数是完整的程序集路径。
3、使用示例:
相关源码:https://files.cnblogs.com/files/pilgrim/MyReflection.rar
3.1、加载程序集,获取对应的特性和创建对象:
Console.WriteLine("*****************Reflection***********");
Assembly assembly = Assembly.Load("DB.MySql");//获取当前路径下的dll,不需要后缀
Module[] modules = assembly.GetModules();//获取程序集中的所有模块
Type[] types = assembly.GetTypes();//获取程序中所有的类型
Attribute[] attributes= assembly.GetCustomAttributes().ToArray();//获取程序中所有的自定义特性
Type dbHlperType = assembly.GetType("DB.MySql.MySqlHlper");
object oDBHlper = Activator.CreateInstance(dbHlperType);//创建对象(默认构造函数)
DB.Interface.IDBHlper dBHlper = oDBHlper as DB.Interface.IDBHlper;
dBHlper.Query();
为使得程序更加灵活,可以将上面的代码进行修改优化。使用应用程序配置文件+工厂方法,在配置文件中添加代码:
<add key="IDBHlper" value="DB.MySql,DB.MySql.MySqlHlper"/>。
添加类读取相关数据:
public class SimpleFactory
{
/// <summary>
/// 程序集名称
/// </summary>
public static string DllName { get; private set; }
/// <summary>
/// 程序集中的某个类型名称
/// </summary>
public static string TypeName { get; private set; }
static SimpleFactory()
{
//从配置文件中读取数据
string[] iDBHlperConfig = ConfigurationManager.AppSettings["IDBHlper"].Split(',');
DllName = iDBHlperConfig[].Trim();
TypeName = iDBHlperConfig[].Trim();
} /// <summary>
/// 创建实例
/// </summary>
/// <returns></returns>
public static DB.Interface.IDBHlper CreateInstance()
{
Assembly assembly = Assembly.Load(DllName);//加载程序集
Type type = assembly.GetType(TypeName);//获取对应的类型
object dbHlper = Activator.CreateInstance(type);//创建实例
return dbHlper as DB.Interface.IDBHlper;
}
}
在代码调用时使用:
//使用工厂方法创建实例
DB.Interface.IDBHlper dBHlper2 = SimpleFactory.CreateInstance();
dBHlper2.Query();
Console.WriteLine();
3.2、使用程序集调用多构造函数、破坏单例、创建泛型类型等:
Assembly assembly = Assembly.Load("DB.SqlServer");//获取当前路径下的dll,不需要后缀
Type dbHlperType = assembly.GetType("DB.SqlServer.SqlServerHlper");
ConstructorInfo[] constructorInfos = dbHlperType.GetConstructors();//获取所有的公共构造函数
//一个int类型参数的构造函数
object oDBHlper1 = Activator.CreateInstance(dbHlperType, new object[] { });
//一个字符串类型参数的构造函数
object oDBHlper2 = Activator.CreateInstance(dbHlperType,new object[] { "一个字符串参数"});
//一个字符串类型和一个int类型参数的构造函数
object oDBHlper3 = Activator.CreateInstance(dbHlperType, new object[] { "一个字符串和一个int参数", });
//调用私有构造函数
object oDBHlper4 = Activator.CreateInstance(dbHlperType, true);
Console.WriteLine();
//获取泛型类型,其有三个泛型参数
Type genericType = assembly.GetType("DB.SqlServer.GenericType`3");//`3是占位符,三个泛型参数
//将三个泛型参数类型的泛型创建为: float int string类型的类
Type type = genericType.MakeGenericType(typeof(float), typeof(int), typeof(string));
object oGeneric = Activator.CreateInstance(type);
Console.WriteLine(oGeneric.ToString());
3.3、使用反射调用实例方法、静态方法、私有方法等:
Assembly assembly = Assembly.Load("DB.MySql");//获取当前路径下的dll,不需要后缀
Type type = assembly.GetType("DB.MySql.MySqlHlper");
object obj = Activator.CreateInstance(type);//创建对象(默认构造函数)
foreach (var item in type.GetMethods())
{
Console.WriteLine(item.Name);
}
MethodInfo method = type.GetMethod("Query", new Type[] { } );//如果重载了,必须传入参数类型
method.Invoke(obj, null);//谁调用,调用传入的参数
//method.Invoke(null, null);//该方法只适用于静态函数
MethodInfo method1 = type.GetMethod("Query", new Type[] { typeof(int) });
method1.Invoke(obj, new object[] { });//谁调用,调用传入的参数
MethodInfo method2 = type.GetMethod("Query",new Type[] { typeof(string)});
method2.Invoke(obj, new object[] { "字符串" });//谁调用,调用传入的参数
C#反射的基本应用的更多相关文章
- 隐私泄露杀手锏 —— Flash 权限反射
[简版:http://weibo.com/p/1001603881940380956046] 前言 一直以为该风险早已被重视,但最近无意中发现,仍有不少网站存在该缺陷,其中不乏一些常用的邮箱.社交网站 ...
- Java学习之反射机制及应用场景
前言: 最近公司正在进行业务组件化进程,其中的路由实现用到了Java的反射机制,既然用到了就想着好好学习总结一下,其实无论是之前的EventBus 2.x版本还是Retrofit.早期的View注解框 ...
- 关于 CSS 反射倒影的研究思考
原文地址:https://css-tricks.com/state-css-reflections 译者:nzbin 友情提示:由于演示 demo 的兼容性,推荐火狐浏览.该文章篇幅较长,内容庞杂,有 ...
- 编写高质量代码:改善Java程序的151个建议(第7章:泛型和反射___建议106~109)
建议106:动态代理可以使代理模式更加灵活 Java的反射框架提供了动态代理(Dynamic Proxy)机制,允许在运行期对目标类生成代理,避免重复开发.我们知道一个静态代理是通过主题角色(Prox ...
- 运用Mono.Cecil 反射读取.NET程序集元数据
CLR自带的反射机智和API可以很轻松的读取.NET程序集信息,但是不能对程序集进行修改.CLR提供的是只读的API,但是开源项目Mono.Cecil不仅仅可以读取.NET程序集的元数据,还可以进行修 ...
- .NET面试题系列[6] - 反射
反射 - 定义,实例与优化 在面试中,通常会考察反射的定义(操作元数据),可以用反射做什么(获得程序集及其各个部件),反射有什么使用场景(ORM,序列化,反序列化,值类型比较等).如果答得好,还可能会 ...
- .NET基础拾遗(4)委托、事件、反射与特性
Index : (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理基础 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 (6)ADO.NET与数据库开 ...
- C++的性能C#的产能?! - .Net Native 系列五:.Net Native与反射
此系列系小九的学堂原创翻译,翻译自微软官方开发向导,一共分为六个主题.本文是第五个主题:.Net Native与反射. 向导文链接:<C++的性能C#的产能?! - .Net Native 系列 ...
- [源码]Literacy 快速反射读写对象属性,字段
Literacy 说明 Literacy使用IL指令生成方法委托,性能方面,在调用次数达到一定量的时候比反射高很多 当然,用IL指令生成一个方法也是有时间消耗的,所以在只使用一次或少数几次的情况,不但 ...
- SI与EMI(一) - 反射是怎样影响EMI
Mark为期两天的EMC培训中大概分成四个时间差不多的部分,简单来说分别是SI.PI.回流.屏蔽.而在信号完整性的书籍中,也会把信号完整性分为:1.信号自身传输的问题(反射,损耗):2.信号与信号之间 ...
随机推荐
- 设置VS2010和IE8 调试ATL控件<转>
VS2010设置篇: 设置VS2010 通过IE8 调试ATL的ActiveX控件的步骤如下: 设置项目属性 在项目的属性页对话框中选中“配置属性—>调试”,在右边填入下列参数: 命令 ...
- UNITY引擎变量调用产生不必要内存分配
https://unity3d.com/de/learn/tutorials/topics/performance-optimization/optimizing-garbage-collection ...
- ELK-Stack 最后一次全篇文档
简介: ELK-Stack 日志收集系统.最后一次全篇记录的笔记,之后关于 ELK 的笔记都将是片段型.针对性的. 环境介绍: ELK-Stack:192.168.1.25 ( Redis.LogS ...
- 改bug的乐趣
一直以来,我都不喜欢改bug,不管是自己的,还是别人的.因为我不相信自己的代码会出现问题,一旦出现问题我就会觉得很难堪,因为我觉得我的代码没什么问题.然后我就不知道该怎么来解决这些问题. 最近这一两次 ...
- NHibernate注意事项
1.检查映射文件是否正确 2.检查配置文件的“嵌入的资源”选项 3.检查Configuration是否加载了程序集
- java 蓝桥杯算法提高 出现次数最多的整数
思路:其实这道题不是太难,但是这个题太坑了,提交了好多次都不是100,后来才知道,一定一定要在输入数组数据之前先判断一下输进去的n的范围,一定一定要注意,否则就是跟我下面的图片一样的效果了,泪奔~ 问 ...
- C#中实例Singleton
[C#中实例Singleton] 1.经典方案: using System; public class Singleton { private static Singleton instance; p ...
- Linux 安装elasticsearch、node.js、elasticsearch-head
前提:下载es的安装包 官网可以下载 es官网 安装elasticsearch 1 新建两个文件夹 一个存放安装文件,一个存放解压后的文件 mkdir -p /export/software //存放 ...
- 解决svn Key usage violation in certificate has been detected
ubuntu系统 #!/bin/shecho "This script will reconfigure subversion to work with certs correctly.&q ...
- 机器学习模型数据结构:logistic regression, neural network, convolutional neural network
可以用两种方式来看神经网络,一种就是层的集合,也就是层组成的数组,另一种是神经元的集合,也就是神经元组成的Graph. 基于神经元的实现方式中,需要定义两个类 Neuron, Weight Neuro ...