【Unity|C#】基础篇(12)——反射(Reflection)(核心类:Type、Assembly)
【学习资料】
《C#图解教程》(第24章):https://www.cnblogs.com/moonache/p/7687551.html
电子书下载:https://pan.baidu.com/s/1mhOmBG0
【内容】
对以下文章的整合:
知识点:
- 用途
- 命名空间
- 主要类: System.Type System.Reflection.Assembly
- System.Type类
- 说明
- 获取给定类型的Type的3种方式
- Type类的 常用属性
- Type类的 常用方法
- 用反射生成对象
- ConstructorInfo
- Activator.CreateInstance
- 使用Type反射举例(创建对象、获取并设置字段或属性、调用方法)
- Assembly类
- 用途
- Assembly常用方法
- 使用举例
- 扩展知识
- Assembly三种加载方式(Load、LoadFrom、LoadFile)的区别
【文章整合笔记】
- .NET的应用程序由几个部分:程序集(Assembly)、模块(Module)、类型(class)组成。
- 反射是.NET中的重要机制,通过反射,可以 在运行时,获得程序或程序集中 每一个类型(包括类、结构、委托、接口和枚举等)的 成员和成员的信息。
- 有了反射,即可对每一个类型了如指掌。另外我还可以直接创建对象,即使这个对象的类型在编译时还不知道。

- 用途
- Assembly :定义和加载程序集,加载在程序集清单中列出模块,以及从此程序集中查找类型并创建该类型的实例。
- Module :了解包含 模块 的程序集以及模块中的类等,还可以获取在模块上定义的所有全局方法或其他特定的非全局方法。
- ConstructorInfo:了解 构造函数 的名称、参数、访问修饰符(如pulic 或private)和实现详细信息(如abstract或virtual)等。
- ParameterInfo :了解 参数 的名称、数据类型、是输入参数还是输出参数,以及参数在方法签名中的位置等。
- EventInfo :了解 事件 的名称、事件处理程序数据类型、自定义属性、声明类型和反射类型等,添加或移除事件处理程序。
- FiedInfo :了解 字段 的名称、访问修饰符(如public或private)和实现详细信息(如static)等,并获取或设置字段值。
- PropertyInfo :了解 属性 的名称、数据类型、声明类型、反射类型和只读或可写状态等,获取或设置属性值。
- MethodInfo :了解 方法 的名称、返回类型、参数、访问修饰符(如pulic 或private)和实现详细信息(如abstract或virtual)等。
- 用到的命名空间
- System.Reflection
- System.Type
- System.Reflection.Assembly
- 用到的主要类
- System.Type 类 // 通过这个类可以访问任何给定数据类型的信息。
- System.Reflection.Assembly 类 // 它可以用于访问给定程序集的信息,或者把这个程序集加载到程序中。
- System.Type类
- System.Type 类对于反射起着核心的作用
- 但它是一个抽象的基类,Type有与每种数据类型对应的派生类,我们使用这个派生类的对象的方法、字段、属性来查找有关该类型的所有信息
- 程序中用到的每一个类型,CLR都会创建一个包含这个类型信息的Type类型的对象
- 程序中用到的每一个类型,都会关联到独立的Type类型的对象
- 不管创建的类型有多少个实例,只有一个Type对象会关联到所有这些实例

- 获取给定类型Type引用的 3种方式:
- typeof()
Type t = typeof(string);
- object.GetType()
string s = "hello";
Type t = s.GetType();- Type.GetType() :类型的完整名称(包含命名空间名)
Type t = Type.GetType("System.String");
- Type类的常用属性 (以string为例)

- Type类的常用方法
- 注:只能获取 public 的成员(字段、属性、方法、事件、构造函数)

- 通过反射生成对象
- 用 ConstructorInfo 生成对象
System.Type t = typeof(string);
// 获取参数为char[]的构造函数: string(char[])
System.Reflection.ConstructorInfo ci = t.GetConstructor(new Type[] { typeof(char[]) });
// 等价于 object obj = new string( new char[] { 'h', 'e', 'l', 'l', 'o' } )
object obj = ci.Invoke(new object[] { new char[] { 'h', 'e', 'l', 'l', 'o' } });
- 用 Activator 生成对象
System.Type t = typeof(string);
// 等价于 object obj = new string( new char[] { 'h', 'e', 'l', 'l', 'o' } )
object obj2 = Activator.CreateInstance(t, new char[] { 'h', 'e', 'l', 'l', 'o' });
- 用 ConstructorInfo 生成对象
- 使用Type反射举例(创建对象、获取并设置字段或属性、调用方法)
public class MyTest
{
// 字段
public int value1 = ;
private int value2 = ;
// 属性
public string name1 { get; set; } = "hello";
protected string name2 { get; set; } = "world";
// 方法
public void Show1() { Debug.Log(name1 + value1); }
internal void Show2() { Debug.Log(name2 + value2); }
} void Start()
{
// 获取 MyTest类 的 Type类型
Type t = typeof(MyTest); // 使用Activator创建对象
object obj = Activator.CreateInstance(t); // 获取字段
FieldInfo obj_value1 = t.GetField("value1");
FieldInfo obj_value2 = t.GetField("value2"); // null,无法获取 private 字段
// 获取属性
PropertyInfo obj_name1 = t.GetProperty("name1");
PropertyInfo obj_name2 = t.GetProperty("name2"); // null,无法获取 protected 字段
// 获取方法
MethodInfo obj_Show1 = t.GetMethod("Show1");
MethodInfo obj_Show2 = t.GetMethod("Show2"); // null,无法获取 internal 字段 // 设置字段 SetValue
obj_value1.SetValue(obj, );
// 设置属性 SetValue
obj_name1.SetValue(obj, "heihei");
// 调用方法 Invoke
obj_Show1.Invoke(obj, null);
}- 运行结果

- Assembly类
- 用途
- 使用Assembly类可以降低程序集之间的耦合,有利于软件结构的合理化
- 获得程序集的信息
- 动态的加载程序集
- 在程序集中查找类型信息
- 创建该类型的实例
- 常用的方法

- 使用举例
namespace MyNameSpace
{
public class LearnCS : MonoBehaviour
{
public class MyTest
{
public class MySubTest { }
} void Start()
{
// 加载程序集,获取Assembly实例
Assembly ass1 = Assembly.Load("Assembly-CSharp");
Assembly ass2 = Assembly.LoadFrom("C:/E/Projects/Demo/Library/ScriptAssemblies/Assembly-CSharp.dll");
Assembly ass3 = Assembly.LoadFile("C:/E/Projects/Demo/Library/ScriptAssemblies/Assembly-CSharp.dll"); // 获取MyTest类型所在的程序集Assembly
Assembly ass = Assembly.GetAssembly(typeof(MyTest));
// 获取当前运行的程序集Assembly
Assembly assembly = Assembly.GetExecutingAssembly(); // 获取程序集名称信息
string assembly_FullName = assembly.FullName;
AssemblyName assembly_Name = assembly.GetName();
// 获取程序集路径
string assembly_CodeBase = assembly.CodeBase;
string assembly_Location = assembly.Location; // 获取Type
Type[] types = assembly.GetTypes();
Type t = assembly.GetType("MyNameSpace.LearnCS+MyTest"); // 通过Type的FullName // 创建实例
var obj = assembly.CreateInstance("MyNameSpace.LearnCS+MyTest"); // 通过Type的FullName
}
}
}
- 运行结果

【扩展知识】
- Assembly三种加载方式(Load、LoadFrom、LoadFile)的区别
- Load
- 使用 程序集名 加载,Load("xxx")
- 同时会 加载依赖 的其他程序集
- 效率最高,优先使用这个方式
- LoadFrom
- 使用 路径 加载,LoadFrom("x/xx/xxx.dll")
- 可以通过URL加载("http://www.abc.com/test.dll"),会被下载到缓存文件中
- 同时会 加载依赖 的其他程序集
- 加载过的程序集,不会重新加载
- 不能用于加载标识相同但路径不同的程序集
- LoadFile
- 使用 路径 加载,LoadFile("x/xx/xxx.dll")
- 不会加载依赖 的程序集
- 可以多次加载同一个程序集
- 可以用来加载和检查具有相同标识但位于不同路径中的程序集,但不会加载程序的依赖项
- Load
【Unity|C#】基础篇(12)——反射(Reflection)(核心类:Type、Assembly)的更多相关文章
- python 基础篇 12 装饰器进阶
本节主要内容:1. 通⽤装饰器回顾2. 函数的有⽤信息3. 带参数的装饰器4. 多个装饰器同时装饰⼀个函数 ⼀. 通⽤装饰器的回顾开闭原则: 对增加功能开放. 对修改代码封闭装饰器的作⽤: 在不改变原 ...
- Java 基础篇之反射
反射 使用反射获取程序运行时的对象和类的真实信息. 获取 Class 对象 每个类被加载之后,系统会为该类生成一个对应的 Class 对象,通过该 Class 对象可以访问到 JVM 中的这个类. 使 ...
- cocos2dx基础篇(12) 编辑框之一CCTextFieldTTF
前面我们讲了精灵贴图.标签.菜单.按钮.感觉似乎少了点什么?UI控件里是不是应该还有一个很重要的控件--编辑框.在手机网游中,启动游戏,过了开场动画后,基本上显示的第一个界面应该就是游戏的登录界面了吧 ...
- 【Unity|C#】基础篇(18)——正则表达式(Regex类)
[学习资料] <C#图解教程>:https://www.cnblogs.com/moonache/p/7687551.html 电子书下载:https://pan.baidu.com/s/ ...
- Unity热更新之C#反射动态获取类属性及方法
如果我们要为发布出去的游戏更新一些功能,但又不想让用户重新下载整个游戏包,只让他下载我们更新的资源包,用assetBundle打包资源的方式是可以的,但其中有个最大的例外,那就是脚本. 虽然asset ...
- java 编程基础 Class对象 反射 :获取类的构造方法,方法,成员变量,内部类,外部类,父类,实现的接口,修饰符等...
类 Class 每个类被加载之后,系统就会为该类生成一个对应的Class对象,通过该Class对象就可以访问到JVM中的这个类. 我们在Java中获取Class对象一般有三种方式: (1), 使用C ...
- 2000条你应知的WPF小姿势 基础篇<63-68 Triggers和WPF类逻辑结构>
在正文开始之前需要介绍一个人:Sean Sexton. 来自明尼苏达双城的软件工程师.最为出色的是他维护了两个博客:2,000ThingsYou Should Know About C# 和 2,00 ...
- (spring-第17回【AOP基础篇】) 创建增强类
一. 增强类包含的信息: a) 横切逻辑(插入的具体代码) b) 部分连接点信息(在方法的哪个位置插入代码,比如方法前.方法后等). 二. 增强的类型 每一种增强有一个需要实现的增强类 ...
- java基础篇---反射机制
一.JAVA是动态语言吗? 一般而言,说到动态言,都是指在程序运行时允许改变程序结构或者变量类型,从这个观点看,JAVA和C++一样,都不是动态语言. 但JAVA它却有着一个非常突出的动态相关机制:反 ...
随机推荐
- 利用django打造自己的工作流平台(三):团队成员任务跟踪系统
近期受疫情影响公司食堂不开放,为解决同事们的吃饭问题,部门需要在每周五统计下周的订餐情况:员工根据个人意愿选择是否从公司订下周的午餐和晚餐,一旦确定一周保持不变. 通常要完成一次部门内员工的订餐信息收 ...
- CoreLocation在iOS8上用法的变化
1.在使用CoreLocation前需要调用如下函数[iOS8专用]: iOS8对定位进行了一些修改,其中包括定位授权的方法,CLLocationManager增加了下面的两个方法: (1)始终允许访 ...
- 惊讶!缓存刚Put再Get居然获取不到?
最近一直在老家远程办公,微信突然响了下,有同事说遇到了一个奇怪的问题,让我帮忙看下. 现象就是标题所说的缓存获取不到的问题,我一听感觉这个问题挺有意思的,决定一探究竟. 下面给出部分代码还原下案发现场 ...
- 写入时复制(CopyOnWrite)
一.CopyOnWrite 思想 写入时复制(CopyOnWrite,简称COW)思想是计算机程序设计领域中的一种通用优化策略.其核心思想是,如果有多个调用者(Callers)同时访问相同的资源(如内 ...
- 使用 Apache James 3.3.0(开源免费) 搭建外网电子邮件服务器(基于 Windows + Amazon Corretto 8)
对于邮件服务器的安装,请先参阅: 使用 Apache James 3.3.0(开源免费) 搭建内网电子邮件服务器(基于 Windows + Amazon Corretto 8) https://www ...
- .NET CLI简单使用
官方文档https://docs.microsoft.com/zh-cn/dotnet/core/tools/?tabs=netcore2x 创建新项目 查看能创建什么类型的项目 dotnet new ...
- 记录 Spine骨骼动画导入unity 步骤[unity3d 4.6.6版本 2d动画]
1:准备好unity使用Spine所需要的运行库,可到如下地址 https://github.com/EsotericSoftware/spine-runtimes/tree/master/spine ...
- MySQL基础(3) | 函数
MySQL基础(3) | 函数 前言 MySQL只有标量值函数的概念,没有SqlServer那种表值函数. 语法 创建 create function f_add( a int, b int ) re ...
- day19 几个模块的学习
# 模块本质上就是一个 .py 文件# 数据类型# 列表.元组# 字典# 集合.frozenset# 字符串# 堆栈:特点:先进后出# 队列:先进先出 FIFO # from collections ...
- opencv —— resize、pyrUp 和 pyrDown 图像金字塔(高斯金字塔、拉普拉斯金字塔)与尺寸缩放(向上采样、向下采样)
我们经常会将某种尺寸的图像转化为其他尺寸的图像,如果需要放大或者缩小图像的尺寸,在 OpenCV 中可以使用如下两种方法: resize 函数,最直接的方法. pyrUp 和 pyrDown 函数,即 ...