C# 反射的乌云,MethodInfo的Json序列化参数入参问题

文章目录

  • 前言
  • 直接运行MethodInfo
    • 运行结果
  • Json解决
    • ParamterInfo实例化
      • 运行结果
      • 无法实例化问题部分参数的问题
    • Json反序列化
  • 经过长达一天的研究,我终于完全的解决的了
    • 实战思路
    • 方法
    • 测试用例
    • 运行测试
    • 运行结果
  • 代码总结
  • 总结

前言

我上篇文章已经基本解决了反射的基本问题,现在只留下了一乌云,就是Json化对象如何转化为MethodInfo 的参数入参

C# 反射的终点:Type,MethodInfo,PropertyInfo,ParameterInfo,Summry

但是反射的问题还有一朵解决不了的乌云,Json字符串参数入参MethodInfo。

直接运行MethodInfo

我们直接写一个简单的函数

在这里插入图片描述

        /// <summary>/// /// </summary>/// <param name="age"></param>/// <param name="name"></param>/// <param name="person"></param>public void TestParamters(int age, string name, T_Person person){Console.WriteLine(JsonConvert.SerializeObject(new { age = age, name = name, person = person }));}
static void Main(string[] args)
{//从程序集中拿出SwitchService switchService = new SwitchService();var method = typeof(SwitchService).GetMethod("TestParamters");if (method != null){//默认方法method.Invoke(switchService, new object[] { 15, "小天", new T_Person() });}Console.WriteLine("运行完成!");Console.ReadKey();
}

运行结果

在这里插入图片描述
这个是非常好解决的,但是有个问题,我们运行反射的时候根本不知道如何入参的个数和类型。我们还需要解决Json到Paramters的问题

Json解决

ParamterInfo实例化

static void Main(string[] args){//从程序集中拿出SwitchService switchService = new SwitchService();var method = typeof(SwitchService).GetMethod("TestParamters");//需要反序列化的字符串var paramterStr = @"{""age"":0,""name"":null,""person"":{""Name"":null,""Age"":0,""Sex"":null}}";if (method != null){//默认方法method.Invoke(switchService, new object[] { 15, "小天", new T_Person() });var parameterInfos = method.GetParameters();object[] methodParams = new object[parameterInfos.Length];for (int i = 0; i < parameterInfos.Length; i++){var item = parameterInfos[i];//通过程序集创建实例化对象Type itemType = item.ParameterType;try{//无法实例化无默认构造函数的方法methodParams[i] = System.Activator.CreateInstance(itemType, true);}catch (Exception ex){Console.WriteLine(ex.ToString());}}method.Invoke(switchService, methodParams);//method.Invoke(switchService, new object[] { paramterStr });}//var methods = MyAttributeHelper.GetAllMethods<MySwitchAttribute>(typeof(SwitchService));Console.WriteLine("运行完成!");Console.ReadKey();}

运行结果

在这里插入图片描述

无法实例化问题部分参数的问题

Activator can’t create array and string?

在这里插入图片描述
在这里插入图片描述
简单来说,有些对象就是无法实例化的,默认只能为Null,

Json反序列化

但是我感觉我想的有点多了,我直接把Json对象拆分了不就行了。

但是Json反序列化有个问题,你必须要告诉他这个类是什么,他才能反序列化。就是我们要通过ParamterInfos给出反序列化的模型

TypeConverter.ConvertTo 方法

是否将Dictionary<string、object>转换为匿名对象?

因为Method.invoke必须参数的类型一致,而我默认直接转为Object类型,是有点问题的。

Error : Object must implement IConvertible

经过长达一天的研究,我终于完全的解决的了

安装Json序列化工具
在这里插入图片描述

实战思路

初步序列化
Json
Dictionary字典
MethodInfo
ParametersInfos
找到Name,Type,Value
对找到的object类型的Value重新序列化,因为有歧义,比如int32和int64序列化之后都是一个值
将重新赋值成功的值放在一个数组里面
MethodInfo.Invoke对应参数

方法

/// <summary>
/// Json对象入参
/// </summary>
/// <param name="obj">实例化对象</param>
/// <param name="methodInfo">方法</param>
/// <param name="JsonStr">序列化参数</param>
public static void MethodInfoInvokeJson(object obj ,MethodInfo methodInfo,string JsonStr)
{//获取所有的入参的信息var parametersInfos = methodInfo.GetParameters();//即将入参的对应变量var methodParams = new object[parametersInfos.Length];//反序列化的Json数据var deserializeValues = JsonConvert.DeserializeObject<Dictionary<string, object>>(JsonStr);//找到对应的Json参数for (var i = 0; i < parametersInfos.Length; i++){var parameter = parametersInfos[i];Type parameterType = parameter.ParameterType;//如果存在Key,则取出改值if (deserializeValues.ContainsKey(parameter.Name)){object parameterValue = deserializeValues[parameter.Name];//需要重新序列化对象parameterValue = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(parameterValue), parameterType);methodParams[i] = parameterValue;}}methodInfo.Invoke(obj, methodParams);
}

测试用例

namespace NetCore.Models
{public class T_Person{public string Name { get;set; }public int Age { get; set; }public string Sex { get; set; }}
}
        /// <summary>/// 测试反序列化的方法/// </summary>/// <param name="age"></param>/// <param name="name"></param>/// <param name="person"></param>public void TestParamters( int age, string name, T_Person person){Console.WriteLine(JsonConvert.SerializeObject(new { age = age, name = name, person = person }));}

运行测试

   static void Main(string[] args){//从程序集中拿出SwitchService switchService = new SwitchService();var method = typeof(SwitchService).GetMethod("TestParamters");//需要反序列化的字符串var paramterStr = @"{""age"":0,""name"":""小刘"",""person"":{""Name"":null,""Age"":0,""Sex"":null}}";try{//执行序列化方法MethodInfoInvokeJson(switchService, method, paramterStr);    }catch (Exception ex){Console.WriteLine(ex.ToString());}Console.WriteLine("运行完成!");Console.ReadKey();}

运行结果

在这里插入图片描述

代码总结

C#高级语法 Attribute特性详解和类型,方法,变量附加特性讲解

这个和我之前的特性的方法放在了一起

   public static class MyAttributeHelper{/// <summary>/// 获取该类型下所有的带Attribute的方法/// </summary>/// <typeparam name="T"></typeparam>/// <param name="type"></param>/// <returns></returns>public static List<MethodInfo> GetAllMethods<T>(Type type) where T : class, new(){var res = new List<MethodInfo>();res = type.GetMethods().Where(t => t.GetCustomAttributes(typeof(T), false).Any()).ToList();return res;}/// <summary>/// 获取该类型下所有的带Attribute的属性/// </summary>/// <typeparam name="T"></typeparam>/// <param name="type"></param>/// <returns></returns>public static List<PropertyInfo> GetAllPropertys<T>(Type type) where T : class, new(){var res = new List<PropertyInfo>();res = type.GetProperties().Where(t => t.GetCustomAttributes(typeof(T), false).Any()).ToList();return res;}/// <summary>/// 获取程序集所有有T特性的类型class/// </summary>/// <typeparam name="T"></typeparam>/// <returns></returns>public static List<Type> GetAllTypes<T>() where T : Attribute{var res = new List<Type>();//Assembly存放所有的程序集res = Assembly.GetExecutingAssembly().GetTypes().Where(t => t.GetCustomAttributes(typeof(T), false).Any())//我们找到所有程序集中带有T特性的Type类型.ToList();return res;}/// <summary>/// 获取特性/// </summary>/// <typeparam name="T"></typeparam>/// <param name="model"></param>/// <returns></returns>public static T GetAttribute<T>(Type type) where T : Attribute, new(){var res = new T();res = type.GetCustomAttribute<T>();return res;}/// <summary>/// 获取特性/// </summary>/// <typeparam name="T"></typeparam>/// <param name="model"></param>/// <returns></returns>public static T GetAttribute<T>(MethodInfo type) where T : Attribute, new(){var res = new T();res = type.GetCustomAttribute<T>();return res;}/// <summary>/// 获取特性/// </summary>/// <typeparam name="T"></typeparam>/// <param name="model"></param>/// <returns></returns>public static T GetAttribute<T>(PropertyInfo type) where T : Attribute, new(){var res = new T();res = type.GetCustomAttribute<T>();return res;}/// <summary>/// 返回带有Attribute的类型元祖列表/// </summary>/// <typeparam name="Att"></typeparam>/// <returns></returns>public static List<(Type type, Att att)> GetAll_TypeAndAtt<Att>() where Att : Attribute, new(){var res = new List<(Type type, Att att)> ();var typeLists = GetAllTypes<Att>();foreach (var item in typeLists){var att = GetAttribute<Att>(item);res.Add((item, att));   }return res;}/// <summary>/// 返回带有Attribute的变量元祖列表/// </summary>/// <typeparam name="Att"></typeparam>/// <param name="type"></param>/// <returns></returns>public static List<(PropertyInfo property, Att att)> GetAll_PropertyAndAtt<Att>(Type type) where Att : Attribute, new(){var res = new List<(PropertyInfo type, Att att)>();var typeLists = GetAllPropertys<Att>(type);foreach (var item in typeLists){var att = GetAttribute<Att>(item);res.Add((item, att));}return res;}/// <summary>/// 返回带有Attribute的方法元祖列表/// </summary>/// <typeparam name="Att"></typeparam>/// <param name="type"></param>/// <returns></returns>public static List<(MethodInfo method, Att att)> GetAll_MethodAndAtt<Att>(Type type) where Att : Attribute, new(){var res = new List<(MethodInfo type, Att att)>();var typeLists = GetAllMethods<Att>(type);foreach (var item in typeLists){var att = GetAttribute<Att>(item);res.Add((item, att));}return res;}/// <summary>/// Json对象入参/// </summary>/// <param name="obj">实例化对象</param>/// <param name="methodInfo">方法</param>/// <param name="JsonStr">序列化参数</param>public static void MethodInfoInvokeJson(object obj, MethodInfo methodInfo, string JsonStr){//获取所有的入参的信息var parametersInfos = methodInfo.GetParameters();//即将入参的对应变量var methodParams = new object[parametersInfos.Length];//反序列化的Json数据var deserializeValues = JsonConvert.DeserializeObject<Dictionary<string, object>>(JsonStr);//找到对应的Json参数for (var i = 0; i < parametersInfos.Length; i++){var parameter = parametersInfos[i];Type parameterType = parameter.ParameterType;//如果存在Key,则取出改值if (deserializeValues.ContainsKey(parameter.Name)){object parameterValue = deserializeValues[parameter.Name];//需要重新序列化对象parameterValue = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(parameterValue), parameterType);methodParams[i] = parameterValue;}}methodInfo.Invoke(obj, methodParams);}}

总结

我经过一天的研究,终于解决了这个Json化对象这朵反射的乌云。但是如果要和Attribute联合使用,那么就要用到传说中的IOC容器了。接下来我会解决一下Attrbute实战的一些问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/609230.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

众和策略:沪指跌0.91%险守2900点,半导体、金融等板块走低

8日早盘&#xff0c;两市股指低开低走&#xff0c;沪指一度失守2900点&#xff0c;深成指、创业板指跌约1%&#xff0c;科创50指数创前史新低。 到午间收盘&#xff0c;沪指跌0.91%报2902.4点&#xff0c;深成指跌1.17%&#xff0c;创业板指跌0.99%&#xff0c;科创50指数跌超…

python每日学12:面向对象的编程

背景&#xff1a;最近有些时间&#xff0c;打算把python每日学的计划继续执行起来。由于不知道从何入手&#xff0c;就暂定从学习《python学习手册》开始&#xff0c;这本书也是python领域的一本权威著作&#xff0c;各方面都写的非常详细&#xff0c;读起来很有帮助&#xff0…

pythonPandas四:数据操作与转换

当涉及到数据操作和转换时&#xff0c;Pandas提供了许多有用的功能。以下是一些示例说明&#xff1a; 1.数据选择和操作&#xff1a; import pandas as pd# 创建一个示例DataFrame data {Name: [Alice, Bob, Charlie],Age: [25, 30, 35],City: [New York, London, Paris]} d…

HTTP 请求参数之三种格式

Query String Parameters 、Form Data 、 Request Payload 三种格式的区别。主要是因为 Content-Type&#xff08;用于表明发送数据流的类型&#xff09; 与请求方式 method 不同&#xff0c;导致传递的数据格式不同。 1. Query String Parameters 格式&#xff1a; ?keyvalu…

07GoF之三种工厂模式

GoF&#xff08;Gang of Four&#xff09;:四人组,《Design Patterns: Elements of Reusable Object-Oriented Software》&#xff08;《设计模式》)的作者,设计了23种设计模式.但时代发展,还有其它的设计模式&#xff0c;比如&#xff1a;JavaEE的设计模式&#xff08;DAO模式…

VSCode安装GitHub Copilot插件方法

VSCode安装GitHub Copilot插件的步骤及注意事项如下&#xff1a; 安装步骤&#xff1a; 确保系统要求&#xff1a; 确保你正在使用的Visual Studio Code版本是最新的&#xff0c;且支持GitHub Copilot。同时&#xff0c;Copilot需要你的操作系统是Windows、macOS或Linux&#x…

如何通过PreMaint状态监测发现设备故障:以振动监测为例

在现代工业环境中&#xff0c;设备的健康状况对于维持生产效率至关重要。计划外停机可能导致巨大的成本损失&#xff0c;因此采用先进的监测技术成为预防性维护的核心策略之一。其中&#xff0c;振动监测作为一种早期故障检测手段&#xff0c;通过PreMaint状态监测系统的引入&a…

【前端面试题】每日一个前端面试专题

一、typeof 与 instanceof 区别?如何instanceof的原理 问题回答思路 typeof和instanceof 都可以检测数据类型&#xff0c;typeof检测如果是基本数据类型返回对应的结果。如果检测是对象的话&#xff0c;默认返回一个object&#xff0c;所以无法区分那种对象。 typeof 数据ins…

组件封装原则

在Vue中封装组件时&#xff0c;遵循低耦合、高内聚、可扩展性和可维护性的原则非常重要。以下是一些实现这些原则的关键点&#xff0c;并结合Vue的实践方式给出案例说明&#xff1a; 1. 单一职责原则&#xff1a; 每个组件专注于一个特定的功能或UI部分&#xff0c;例如&#…

Java动态代理机制,创建代理对象的方法(InvocationHandler,Proxy)

目录 1.什么是动态代理2.如何为Java对象创建一个代理对象 1.什么是动态代理 特点&#xff1a;无侵入式的给代码增加额外的功能。 在Java中&#xff0c;动态代理是一种机制&#xff0c;允许在运行时创建一个代理对象来代替原始对象&#xff0c;并可以在代理对象的方法执行前后追…

Hive操作命令上手手册

内容来自于《大数据Hive离线计算开发实战》 Hive原理 Hive是一个基于Hadoop的数据仓库和分析系统&#xff0c;用于管理和查询大型数据集。以下是Hive的原理&#xff1a; 数据仓库&#xff1a;Hive将结构化的数据文件映射成一张表&#xff0c;并提供类SQL查询功能。用户可以使…

第十五章 ECMAScript6新增的常用语法

文章目录 一、声明关键字二、箭头函数三、解构赋值四、展开运算符五、对字符的补充六、Symbol七、对象的简写语法八、Set和Map九、for-of 一、声明关键字 ES6新增的声明关键字&#xff1a; let&#xff0c;const&#xff1a;声明变量class&#xff1a;声明类import&#xff0c…

《网络是怎样连接的》2.5节图表(自用)

图5.1&#xff1a;ip包结构 图5.2&#xff1a;ip网络包的传输方式 1.以太网的部分也可以替换成其他的东西&#xff0c;例如无线局域网、ADSL、FTTH等&#xff0c;它们都可以替代以太网的角色帮助IP协议来传输网络包 2.根据ARP协议&#xff0c;客户端可以根据ip地址得到下一个路…

最新最简操作系统期末复习(考前速过)

操作系统复习 第一章&#xff08;操作系统引论&#xff09;计算机操作系统包括&#xff1a;操作系统的目标&#xff1a;操作系统的作用&#xff1a;未配置操作系统的计算机系统&#xff1a;单道批处理系统&#xff1a;缺点&#xff1a; 多道批处理系统&#xff1a;优点&#xf…

国际版WPS Office18.6.0

​【应用名称】&#xff1a;WPS Office 【适用平台】&#xff1a;Android 【软件标签】&#xff1a;WPS 【应用版本】&#xff1a;18.5.4 → 18.6.0 【应用大小】&#xff1a;160MB 【软件说明】&#xff1a;WPS Office是使用人数最多的移动办公软件。它具有独有手机阅读…

TypeScript基础

ts学习 目录概述需求&#xff1a; 设计思路实现思路分析1.TypeScript 基础类型2.TypeScript 变量声明3.TypeScript 接口4.TypeScript 类5.TypeScript 函数5.TypeScript 泛型5.TypeScript 枚举TypeScript 类型推论TypeScript 类型兼容性TypeScript 高级类型TypeScript 迭代器和生…

读史笔记(二)

读史笔记&#xff08;二&#xff09; 考古是探求过去人类遗留的物质资料为手段&#xff0c;以研究人类发展进程及其规律为目的&#xff0c;为人们了解人类起源及相关的社会制度&#xff0c;宗教祭祀&#xff0c;生活习俗等提供了一种途径。而在我国&#xff0c;传统的金石学即源…

RoadMap8:C++中类的封装、继承、多态与构造函数

摘要&#xff1a;在本章中涉及C最核心的内容&#xff0c;本文以C中两种基础的衍生数据结构&#xff1a;结构体和类作为引子&#xff0c;从C的封装、继承与多态三大特性全面讲述如何在类这种数据结构进行体现。在封装中&#xff0c;我们讲解了类和结构体的相似性&#xff1b;在继…

自带恒压恒流环路的降压型单片车充专用芯片

一、基本概述 XL2009是一款高效降压型DC-DC转换器&#xff0c;固定180KHz开关频率&#xff0c;可以提供最高2.5A输出电流能力&#xff0c;具有低纹波&#xff0c;出色的线性调整率与负载调整率特点。XL2009内置固定频率振荡器与频率补偿电路&#xff0c;简化了电路设计。 PWM …

Java后端和前端传递的请求参数的三种类型

在 HTTP 请求中&#xff0c;常见的请求参数类型有三种&#xff1a;application/x-www-form-urlencoded、multipart/form-data 和 application/json&#xff08;通常用于 raw 类型&#xff09;。这三种类型主要指的是请求体中的数据格式&#xff0c;其中包括参数的传递方式和编码…