《C#从现象到本质》读书笔记(八)第10章反射
《C#从现象到本质》读书笔记(八)第10章反射
个人感觉,反射其实就是为了能够在程序运行期间动态的加载一个外部的DLL集合,然后通过某种办法找到这个DLL集合中的某个空间下的某个类的某个成员(通过反射可以访问该类所包含的所有成员,不论成员是公有还是私有)。
在.NET中,查看和操作元数据的动作,称为反射。
通过反射我们可以:1)加载一个程序集,这称为动态加载程序集或者晚期绑定。2)获得程序集的托管模块(IL+元数据)。3)获得程序集中(托管模块中的)类型对象(通过元数据)。4)获得类型的成员和方法,反射可以访问类型所有的成员和方法,无论它们是不是私有的。
System.Type类会返回加载堆上的类型对象(包括静态成员和方法表)。
当我们要反射一个类的方法时,首先要获得它的类型对象,然后再使用GetMethods方法获得某个方法,获得方法之后,可以使用Invoke执行方法。
GetMembers方法默认只获得公开的成员,包括自己和类型所有父类的公开成员。
即使成员是私有的或受保护的,通过反射一样可以获得其值,甚至可以对其值进行修改。
class Program
{
static void Main()
{
var shapeList = new List<Shapes> { new Rectangle(), new Circle() };
var method = typeof(Processor).GetMethod("Process"); foreach (var shapes in shapeList)
{
//对每个shapes,获得它的类型,然后构造相应的泛型方法
var generateRef = method.MakeGenericMethod(shapes.GetType()); //调用方法
generateRef.Invoke(new Processor(), null);
} Console.ReadKey();
}
} class Processor
{
public void Process<T>() where T : Shapes, new()
{
var t = typeof(T);
t.GetMethod("Print").Invoke(new T(), null);
}
} class Shapes
{
public void Print()
{
Console.WriteLine("我是形状");
}
} class Rectangle : Shapes
{
public void Print()
{
Console.WriteLine("我是长方形");
}
} class Circle : Shapes
{
public void Print()
{
Console.WriteLine("我是圆形");
}
}
在很多时候反射是唯一的选择,例如晚期绑定:当需要动态加载某个程序集(而不是在程序开始时就加载),需要使用反射。如果系统需要面对的是通用的模型,此时无论是方法也好属性也罢,都是随应用场景而改变的,这种完全需呀动态绑定的场景下自然需要运用反射。
方法的调用有三种主要形式:直接调用,委托调用和反射调用。委托调用又可以分为直接创建强类型委托和使用表达式辅助创建委托两种方式。
性能比较:直接调用>委托调用>通用委托调用>表达式调用>反射调用>委托的DynamicInvoke调用。
反射在ORM中有着广泛的用途。
书中有一个简单的ORM的实现。代码也很详细。
《C#从现象到本质》读书笔记(八)第10章反射的更多相关文章
- SQL Server2012 T-SQL基础教程--读书笔记(8 - 10章)
SQL Server2012 T-SQL基础教程--读书笔记(8 - 10章) 示例数据库:点我 CHAPTER 08 数据修改 8.1 插入数据 8.1.1 INSERT VALUES 语句 8.1 ...
- Javascript高级程序设计读书笔记(第10章 DOM)
第10章 DOM 10.1 节点层次 每个节点都有一个nodeType属性,用于表明节点的类型.任何节点类型必是下面中的一个: Node.Element_NODE(1); NODE.ATTRIBUT ...
- C++ Primer 读书笔记:第10章 关联容器
第10章 关联容器 引: map set multimap multiset 1.pair类型 pair<string, int> anon anon.first, anon.second ...
- 《Android开发艺术探索》读书笔记 (13) 第13章 综合技术、第14章 JNI和NDK编程、第15章 Android性能优化
第13章 综合技术 13.1 使用CrashHandler来获取应用的Crash信息 (1)应用发生Crash在所难免,但是如何采集crash信息以供后续开发处理这类问题呢?利用Thread类的set ...
- 《Android开发艺术探索》读书笔记 (3) 第3章 View的事件体系
本节和<Android群英传>中的第五章Scroll分析有关系,建议先阅读该章的总结 第3章 View的事件体系 3.1 View基本知识 (1)view的层次结构:ViewGroup也是 ...
- 《Linux内核设计与实现》读书笔记——第一、 二章
<Linux内核设计与实现>读书笔记--第一. 二章 标签(空格分隔): 20135321余佳源 第一章 Linux内核简介 1.Unix内核特点 十分简洁:仅提供几百个系统调用并且有明确 ...
- 《Android开发艺术探索》读书笔记 (9) 第9章 四大组件的工作过程
第9章 四大组件的工作过程 9.1 四大组件的运行状态 (1)四大组件中只有BroadcastReceiver既可以在AndroidManifest文件中注册,也可以在代码中注册,其他三个组件都必须在 ...
- CLR via c#读书笔记八:泛型
1.定义泛型类型或方法时,为类型指定的任何变量(比如T)都称为类型参数.使用泛型类型或方法时指定的具体数据类型称为类型实参. 2.System.Collections.Concurrent命名空间提供 ...
- Machine Learning for hackers读书笔记(八)PCA:构建股票市场指数
library('ggplot2') prices <- read.csv('G:\\dataguru\\ML_for_Hackers\\ML_for_Hackers-master\\08-PC ...
随机推荐
- [蓝桥杯]ALGO-185.算法训练_Trash Removal
题目描述: 代码如下: #include <algorithm> #include <cstdio> #include <cstdlib> #include < ...
- 【剑指offer】链表第一个公共子结点
*思路: 先求得两个链表的长度,然后得到长度差diff,再先遍历长链表diff步后,再同时遍历两个链表并比较对象指针. /* public class ListNode { int val; List ...
- Python的Django
1 第一部分目录详解 修改django的项目当中的url中的配置: from django.contrib import admin from django.conf.urls import ur ...
- Zabbix监控进程(进程消失后钉钉报警)
用于python报警的脚本如下:(钉钉机器人的连接需要修改) #!/usr/bin/python3# -*- coding: utf-8 -*-# Author: aiker@gdedu.ml# My ...
- C#中redis订阅后程序不再继续执行
项目开发中使用到了redis订阅功能,在订阅的代码执行成功后,发现本应继续执行的程序断不到点, 经过查看redis订阅的源码,发现订阅成功后,会一直循环执行一个监听频道推送消息的动作,导致后续代码无法 ...
- Nginx 安装配置教程
1.安装 Nginx 的先决条件 依赖库:GCC, PCRE, zlib, OpenSSL . * GCC (Nginx 由 C 语言编写,因此需要在系统上安装一个编译工具) 基本上 Linux 自带 ...
- python函数作用域,嵌套函数,闭包
函数作用域 ...
- linux 僵尸进程查看方式
ps -A -ostat,ppid,pid,cmd |grep -e '^[Zz]' # 结果 Z 169925 49893 [sw] <defunct> Z 169925 120690 ...
- python调用cmd显示中文乱码及调用cmd命令
os.system('dir') 解决方法加上 os.system('chcp 65001') ____________________________________________________ ...
- 深度学习原理与框架-CNN在文本分类的应用 1.tf.nn.embedding_lookup(根据索引数据从数据中取出数据) 2.saver.restore(加载sess参数)
1. tf.nn.embedding_lookup(W, X) W的维度为[len(vocabulary_list), 128], X的维度为[?, 8],组合后的维度为[?, 8, 128] 代码说 ...