C# Reflection反射机制
一、反射
什么是反射
.Net的应用程序由几个部分:‘程序集(Assembly)’、‘模块(Module)’、‘类型(class)’组成;
反射提供一种编程的方式,让程序员可以在程序运行期获得这几个组成部分的相关信息;
Type类可以获得对象的类型信息:方法、构造器、属性、字段;
这些都包含在System.Reflection命名空间下;
程序集(assembly)
.dll编译好的库,里面可能有多个命名空间;.exe可执行文件;这两个种都是程序集;
模块(Module)
C#中没有模块,但提供了类似的功能:静态变量;
在C#中模块的另外一个含义是:
一种可加载单元,它可以包含类型声明和类型实现。模块包含的信息足以使公共语言运行库在模块加载时找到所有的实现位。模块的格式是 Windows 可移植可执行 (PE) 文件格式的扩展。在部署时,模块总是包含在程序集中;
个人觉得C#中没有太注重模块,有另一个概念,命名空间;将多个一类功能的类组合在同一命名空间下;
作用
运行期得到类型信息,修改属性或调用方法;
提高可扩展性;
二、反射方法
测试类,包含有参无参数构造;属性,方法,字段;
//测试类
class Person
{
//构造
public Person(){}
public Person(string name)
{
this.name = name;
}
//字段
string name;
int age;
//属性
public string Name{
get{
return name;
}
set{
name = value;
}
}
//方法
public void SetName(string input)
{
name = input;
}
}
获取字段
通过Type类可获得以下信息;
Person p = new Person
Type t = typeof(p)
//获取所有字段
FieldInfo[] fieldInfos = type.GetFields();
//获取单个字段
FieldInfo fieldInfo = type.GetFields("name");
fieldInfo.SetValue(p,"perilla")
获取属性
Person p = new Person
Type t = typeof(p)
//获取所有属性
PropertyInfo[] propertyInfos = type.GetProperties();
//获取单个属性
PropertyInfo propertyInfo = type.GetProperty("Name");
propertyInfo.SetValue(p,"perilla")
获取方法
Person p = new Person
Type t = typeof(p)
//获取所有属性
MethodInfo[] methodInfos = type.GetMethods();
//获取单个属性
MethodInfo methodInfo = type.GetMethod("SetName");
methodInfo.Invoke(p,"Perilla")
动态创建
Person p = new Person
Type t = typeof(p)
object obj = System.Activator.CreateInstance(t,"Perilla")
//也可以获取构造通过构造创建
三、反射工具类
public class ReflectTool
{
#region 成员读写
/// <summary>
/// 通过参数列表,填充实体类型
/// </summary>
/// <param name="model">实体对象</param>
/// <param name="objs">数据只读器</param>
public static void FillInstanceValue(object model, params object[] objs)
{
Type type = model.GetType();
PropertyInfo[] properties = type.GetProperties();
for (int i = 0; i < objs.Length; i++)
{
properties[i].SetValue(model, objs[i], null);
}
}
/// <summary>
/// 通过kv参数表,填充实体类型
/// </summary>
/// <param name="model">实体对象</param>
/// <param name="objs">数据只读器</param>
public static void FillInstanceValue(object model, Dictionary<string,object> paramDic)
{
Type type = model.GetType();
PropertyInfo[] properties = type.GetProperties();
for (int i = 0; i < paramDic.Count; i++)
{
if (paramDic.ContainsKey(properties[i].Name))
{
properties[i].SetValue(model, paramDic[properties[i].Name]);
}
}
}
public static void FillInstanceField(object model, Dictionary<string, object> paramDic)
{
Type type = model.GetType();
FieldInfo[] fieldInfos = type.GetFields();
for (int i = 0; i < paramDic.Count; i++)
{
if (paramDic.ContainsKey(fieldInfos[i].Name))
{
Type it = fieldInfos[i].GetType();
fieldInfos[i].SetValue(model, paramDic[fieldInfos[i].Name]);
}
}
}
/// <summary>
/// 获取实体相关属性的值
/// </summary>
/// <param name="obj"></param>
/// <param name="propertyName"></param>
/// <returns></returns>
public static object GetInstanceValue(object obj, string propertyName)
{
object objRet = null;
if (!string.IsNullOrEmpty(propertyName))
{
PropertyDescriptor descriptor = TypeDescriptor.GetProperties(obj).Find(propertyName, true);
if (descriptor != null)
{
objRet = descriptor.GetValue(obj);
}
}
return objRet;
}
#endregion
#region 方法调用
/// <summary>
/// 直接调用内部对象的方法/函数或获取属性(支持重载调用)
/// </summary>
/// <param name="refType">目标数据类型</param>
/// <param name="funName">函数名称,区分大小写。</param>
/// <param name="objInitial">如果调用属性,则为相关对象的初始化数据(带参数构造,只能调用Get),否则为Null。</param>
/// <param name="funParams">函数参数信息</param>
/// <returns>运行结果</returns>
public static object InvokeMethodOrGetProperty(Type refType, string funName, object[] objInitial, params object[] funParams)
{
MemberInfo[] mis = refType.GetMember(funName);
if (mis.Length < 1)
{
throw new InvalidProgramException(string.Concat("函数/方法 [", funName, "] 在指定类型(", refType.ToString(), ")中不存在!"));
}
else
{
MethodInfo targetMethod = null;
StringBuilder pb = new StringBuilder();
foreach (MemberInfo mi in mis)
{
if (mi.MemberType != MemberTypes.Method)
{
if (mi.MemberType == MemberTypes.Property)
{
#region 调用属性方法Get
targetMethod = ((PropertyInfo)mi).GetGetMethod();
break;
#endregion
}
else
{
throw new InvalidProgramException(string.Concat("[", funName, "] 不是有效的函数/属性方法!"));
}
}
else
{
#region 检查函数参数和数据类型 绑定正确的函数到目标调用
bool validParamsLen = false, validParamsType = false;
MethodInfo curMethod = (MethodInfo)mi;
ParameterInfo[] pis = curMethod.GetParameters();
if (pis.Length == funParams.Length)
{
validParamsLen = true;
pb = new StringBuilder();
bool paramFlag = true;
int paramIdx = 0;
#region 检查数据类型 设置validParamsType是否有效
foreach (ParameterInfo pi in pis)
{
pb.AppendFormat("Parameter {0}: Type={1}, Name={2}\n", paramIdx, pi.ParameterType, pi.Name);
//不对Null和接受Object类型的参数检查
if (funParams[paramIdx] != null && pi.ParameterType != typeof(object) &&
(pi.ParameterType != funParams[paramIdx].GetType()))
{
#region 检查类型是否兼容
try
{
funParams[paramIdx] = Convert.ChangeType(funParams[paramIdx], pi.ParameterType);
}
catch (Exception)
{
paramFlag = false;
}
#endregion
//break;
}
++paramIdx;
}
#endregion
if (paramFlag == true)
{
validParamsType = true;
}
else
{
continue;
}
if (validParamsLen && validParamsType)
{
targetMethod = curMethod;
break;
}
}
#endregion
}
}
if (targetMethod != null)
{
object objReturn = null;
#region 兼顾效率和兼容重载函数调用
try
{
object objInstance = System.Activator.CreateInstance(refType, objInitial);
objReturn = targetMethod.Invoke(objInstance, BindingFlags.InvokeMethod, Type.DefaultBinder, funParams,
System.Globalization.CultureInfo.InvariantCulture);
}
catch (Exception)
{
objReturn = refType.InvokeMember(funName, BindingFlags.InvokeMethod, Type.DefaultBinder, null, funParams);
}
#endregion
return objReturn;
}
else
{
throw new InvalidProgramException(string.Concat("函数/方法 [", refType.ToString(), ".", funName,
"(args ...) ] 参数长度和数据类型不正确!\n 引用参数信息参考:\n",
pb.ToString()));
}
}
}
/// <summary>
/// 调用相关实体类型的函数方法
/// </summary>
/// <param name="refType">实体类型</param>
/// <param name="funName">函数名称</param>
/// <param name="funParams">函数参数列表</param>
/// <returns>调用该函数之后的结果</returns>
public static object InvokeFunction(Type refType, string funName, params object[] funParams)
{
return InvokeMethodOrGetProperty(refType, funName, null, funParams);
}
#endregion
#region 创建实例
//通过Type创建实例,返回Object
public static object CreateInstance(Type refType, params object[] objInitial)
{
object res = System.Activator.CreateInstance(refType, objInitial);
return res;
}
//通过泛型T创建实例,并返回T
public static T CreateInstance<T>(params object[] objInitial) where T : new()
{
Type refType = typeof(T);
object res = System.Activator.CreateInstance(refType, objInitial);
if (res == null)
{
Debug.LogError("Reflect create T is null");
}
return (T)res;
}
#endregion
}
调用测试
public class Test
{
public Test() { }
public Test(string name) { this.name = name; }
private string name;
public string Name {
get {
//Debug.Log($"PorperityGet:{name}");
return name;
}
set {
name = value;
//Debug.Log($"PorperitySet:{name}");
}
}
public void Func1()
{
Debug.Log("Test.Func1");
}
public void Func2(int para1)
{
Debug.Log($"Test.Func1:{para1}");
}
public void Func3(string para1,int para2)
{
Debug.Log($"Test.Func1:{para1},{para2}");
}
}
void Start()
{
Test obj = new Test();
Type t = obj.GetType();
ReflectTool.InvokeFunction(t, "Func1");
ReflectTool.InvokeFunction(t, "Func2", 5);
ReflectTool.InvokeFunction(t, "Func3", "perilla", 25);
object[] objs = new object[1];
objs[0] = "perilla";
ReflectTool.InvokeMethodOrGetProperty(t, "Name", objs);
ReflectTool.InvokeFunction(t, "Name");
obj.Name = "hhahah";
ReflectTool.FillInstanceValue(obj, "QAQ");
Dictionary<string, object> dic = new Dictionary<string, object>();
dic["Name"] = "QWQ";
ReflectTool.FillInstanceValue(obj, dic);
Debug.Log(ReflectTool.GetInstanceValue(obj, "Name"));
obj = ReflectTool.CreateInstance(t, "skylar") as Test;
Debug.Log(obj.Name);
obj = ReflectTool.CreateInstance<Test>("Rebort");
Debug.Log(obj.Name);
string str = " adfas dfaf ffff dsawee dff ";
str = System.Text.RegularExpressions.Regex.Replace(str, @"\s", "");
Debug.Log(str);
Config config = ConfigTool.GetConfig<Config>(Application.dataPath+"/Config.cfg");
Debug.Log($"ServerAddr:{config.ServerIp};Port:{config.Port}");
}
四、特性
待完善...
C# Reflection反射机制的更多相关文章
- Java进阶之reflection(反射机制)——反射概念与基础
反射机制是Java动态性之一,而说到动态性首先得了解动态语言.那么何为动态语言? 一.动态语言 动态语言,是指程序在运行时可以改变其结构:新的函数可以引进,已有的函数可以被删除等结构上的变化.比如常见 ...
- java学习--Reflection反射机制
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和属性:这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制. ...
- Java之reflection(反射机制)——通过反射操作泛型,注解
一.反射操作泛型(Generic) Java采用泛型擦除机制来引入泛型.Java中的泛型仅仅是给编译器Javac使用的,确保数据的安全性和免去强制类型转换的麻烦.但是编译一旦完成,所有和泛型有关的类型 ...
- PHP的Reflection反射机制
更多内容推荐微信公众号,欢迎关注: 原文地址: http://www.nowamagic.net/php/php_Reflection.php PHP5添加了一项新的功能:Reflection.这个功 ...
- Java的反射机制(Reflection)
反射机制 指可以在运动时加载.探知.使用编译期间完全未知的类 程序在运行状态中,可以动态加载一个只有名称的类,对于任意一个已加载的类,都能够获取这个类的属性和方法:对于任意一个对象可以调用它的任意一个 ...
- Java反射机制(Reflection)
Java反射机制(Reflection) 一.反射机制是什么 Java反射机制是程序在运行过程中,对于任意一个类都能够知道这个类的所有属性和方法;对于任意一个对象都能够调用它的任意一个方法和属性,这种 ...
- Java - 反射机制(Reflection)
Java - 反射机制(Reflection) > Reflection 是被视为 动态语言的关键,反射机制允许程序在执行期借助于 Reflection API 取得任何类的 ...
- 反射机制(reflection)动态相关机制
功能:动态获取类的信息以及动态调用对象的方法. Java反射机制主要提供了以下功能: 1.在运行时判断任意一个对象所属的类. 2.在运行时构造任意一个类的对象. 3.在运行时判断任意一个类所具有的成员 ...
- java反射机制--reflection
反射,reflection,听其名就像照镜子一样,可以看见自己也可以看见别人的每一部分.在java语言中这是一个很重要的特性.下面是来自sun公司官网关于反射的介绍: Reflection is ...
随机推荐
- java 图形化小工具Abstract Window Toolit 事件处理
事件处理设计到了三个对象: EventSource(事件源):事件发生的场所,通常就是各个组件,例如按钮.窗口,菜单等. Event (事件封装了GUI组件上发生的特定事情(通常就是一次用户操作).如 ...
- ESP8266学习实战之UdpClient与UdpSever(FreeRTOS)
Udpclient 任务流程 ①判断是否获取ip地址 新建状态变量 STATION_STATUS stastatus; 调用wifi接口,并判断是否获取IP地址 ·do { stastatus = w ...
- 为dokcer中最简版ubuntu(70M)增加apt安装能力
如果要在docker中安装软件,除了直接找对应的软件镜像,一般我们会先安装Linux系统,然后再在里面安装各种需要的软件. 比如我想安装乌班图,直接下载官方的版本: 这个目前是Ubuntu20.04, ...
- ACwing1015. 摘花生
题目: Hello Kitty想摘点花生送给她喜欢的米老鼠. 她来到一片有网格状道路的矩形花生地(如下图),从西北角进去,东南角出来. 地里每个道路的交叉点上都有种着一株花生苗,上面有若干颗花生,经过 ...
- JAVA微信公众号网页开发——将接收的消息转发到微信自带的客服系统
如果公众号处于开发模式,普通微信用户向公众号发消息时,微信服务器会先将消息POST到开发者填写的url上,无法直接推送给微信自带的客服功能.如果需要把用户推送的普通消息推送到客服功能中,就需要进行代码 ...
- c/c++实现CRC查表及算法
说明 CRC被广泛应用到各个领域.足见其厉害之处 本文介绍的是CRC查表法. 拷贝代码即可使用 CRC 的起始值 本来默认是0, 实际生产中遇到过,CRC初始值为0xFFFF, 故将其初始值以参数的形 ...
- Android物联网应用程序开发(智慧城市)—— 购物信息的存储界面开发
效果: 布局代码: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:an ...
- Java常用的几种设计模式
本来想写点spring相关的东西的,想来想去,先写点设计模式的东西吧 什么是设计模式?套用百度百科的话解释吧 设计模式(Design Pattern)是一套被反复使用.多数人知晓的.经过分类的.代码设 ...
- C/C++ Qt 运用JSON解析库 [基础篇]
JSON是一种简单的轻量级数据交换格式,Qt库为JSON的相关操作提供了完整的类支持,使用JSON解析文件之前需要先通过TextStream流将文件读入到字符串变量内,然后再通过QJsonDocume ...
- Linux-saltstack-1 saltstack的安装与基本配置
@ 目录 一.环境介绍 二.安装saltstack 1.配置安装yum源 2.安装salt-master 3.安装slat-minion 三.配置salt-master 1.指定master的地址 2 ...