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 ...
随机推荐
- git 生成ssh
- 大小端(内存、寄存器、CPU)
CPU能进行32位操作,关键是寄存器有32位,数据总线也有32位. 为了表示方便,我们可以把32位寄存器从左到右,与内存中一个双字的四个字节地址从低到高对应. 如果CPU把寄存器的左端定义为高位,则带 ...
- IO复用的三种方法(select,poll,epoll)深入理解
(一)IO复用是Linux中的IO模型之一,IO复用就是进程告诉内核需要监视的IO条件,使得内核一旦发现进程指定的一个或多个IO条件就绪,就通过进程处理,从而不会在单个IO上阻塞了,Linux中,提供 ...
- SQL Server日志恢复还原数据
通过日志还原,首先要注意的是: 1,在数据库更新和删除之前有一个完整的备份. 2,在更新和删除之后,做一个日志备份. 3,该日志只能用于还原数据库备份和日志备份时间之间的数据. 下面看整个数据库备份和 ...
- ACwing1211. 蚂蚁感冒
题目: 长 100 厘米的细长直杆子上有 n 只蚂蚁. 它们的头有的朝左,有的朝右. 每只蚂蚁都只能沿着杆子向前爬,速度是 1 厘米/秒. 当两只蚂蚁碰面时,它们会同时掉头往相反的方向爬行. 这些蚂蚁 ...
- 关于Spring MVC的问题
一.SpringMVC的流程是什么? 1. 用户发送请求至前端控制器DispatcherServlet: 2. DispatcherServlet收到请求后,调用HandlerMapping处理器映射 ...
- JAVA获取本机的MAC地址
/** * 获取本机的Mac地址 * @return */ public String getMac() { InetAddress ia; byte[] mac = null; try { // 获 ...
- 【转】最短路径——Dijkstra算法和Floyd算法
[转]最短路径--Dijkstra算法和Floyd算法 标签(空格分隔): 算法 本文是转载,原文在:最短路径-Dijkstra算法和Floyd算法 注意:以下代码 只是描述思路,没有测试过!! Di ...
- 分布式(CAP)
1. Consistency ------->C---------->一致性[写操作之后的读操作,必须返回该值] 2. Availability-------->A-------- ...
- 「HAOI2016」找相同字符
知识点: SA,线段树,广义 SAM 原题面 Loj Luogu 给定两字符串 \(S_1, S_2\),求出在两字符串中各取一个子串,使得这两个子串相同的方案数. 两方案不同当且仅当这两个子串中有一 ...