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.hqwc.cn/news/334677.html

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

相关文章

vivado 创建编译后工程

创建后期合成项目 合成后项目以合成网表、完全生成的块设计、完全生成的IP以及相应的约束。然后&#xff0c;您可以分析、布局和实施设计 注意&#xff1a;您可以使用XST或第三方合成工具来创建合成网表。 重要&#xff01;使用EDIF和NGC文件时&#xff0c;顶部单元格名称必…

OpenAI ChatGPT-4开发笔记2024-03:Chat之Tool和Tool_Call(含前function call)

Updates on Function Calling were a major highlight at OpenAI DevDay. In another world,原来的function call都不再正常工作了&#xff0c;必须全部重写。 function和function call全部由tool和tool_choice取代。2023年11月之前关于function call的代码都准备翘翘。 干嘛…

Python操作excel-读取、表格填充颜色区分

1.场景分析 遇到一个需要读取本地excel数据&#xff0c;处理后打入到数据库的场景&#xff0c;使用java比较重&#xff0c;python很好的解决了这类问题 2.重难点 本场景遇到的重难点在于&#xff1a; 需要根据表格内的背景颜色对数据进行筛选 读取非默认Sheet 总是出现Value…

vue3 封裝一个常用固定按钮组件(添加、上传、下载、删除)

效果图 这个组件只有四个按钮&#xff0c;添加&#xff0c;上传、下载、删除&#xff0c;其中删除按钮的颜色默认是灰色&#xff0c;当表格有数据选中时再变成红色 实现 组件代码 <script lang"ts" setup> import { Icon } from /components/Icon/index im…

swaggerUI不好用,试试这个openapiUI?

title: swaggerUI不好用&#xff0c;试试这个openapiUI? date: 2024-01-08 categories: [tool] tags: [openapi,工具] description: 基于swaggger2, openapi3规范的UI文档 1.背景 由于长期使用 swaggerUI 工具&#xff0c;它的轻量风格个人觉得还是不错的&#xff0c;但是它…

在python里面探索web框架

一、常识性知识 python Web框架三巨头&#xff1a;Flask&#xff08;简单易学&#xff09;、Django(复杂庞大)、FastAPI 1. Django&#xff1a;Django是一个高级的Web框架&#xff0c;它提供了强大的功能和工具&#xff0c;用于快速开发复杂的Web应用程序。 2. Flask&#xff…

Nginx配置反向代理实例一

Mac 安装Nginx教程 提醒一下&#xff1a;下面实例讲解是在Mac系统演示的&#xff1b; 反向代理实例一实现的效果 在浏览器地址栏输入www.testproxy.com, 跳转到系统Tomcat主页面。 反向代理准备工作 第一步&#xff1a;在系统的 hosts 文件进行ip和域名对应关系的配置。 …

Pytest自动化测试框架

1、pytest简介 pytest是Python的一种单元测试框架&#xff0c;与python自带的unittest测试框架类似&#xff0c;但是比unittest框架使用起来更简洁&#xff0c;效率更高。 执行测试过程中可以将某些测试跳过&#xff0c;或者对某些预期失败的case标记成失败能够支持简单的单元…

蜗牛目标检测数据集VOC格式480张

蜗牛&#xff0c;一种缓慢而坚韧的软体动物&#xff0c;以其螺旋形的外壳和黏附力极强的黏液而为人所熟知。 蜗牛体型呈螺旋形&#xff0c;有一个硬壳保护其柔软的身体。壳的形状和纹理因种类而异&#xff0c;有的光滑如玻璃&#xff0c;有的则布满细纹。蜗牛的头部有两对触角…

【算法Hot100系列】在排序数组中查找元素的第一个和最后一个位置

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老导航 檀越剑指大厂系列:全面总结 jav…

一台智能汽车会使用哪些芯片

目录 1.汽车芯片技术逻辑 2.汽车芯片产品详解和厂商一览 2.1 控制芯片 2.2 计算芯片 2.3 传感芯片 2.4 通信芯片 2.5 存储芯片 2.6 安全芯片 2.7 功率芯片 2.8 驱动芯片 2.9 电源管理芯片 2.10 系统基础芯片 3.小结 这两天算是和标准杠上了&#xff0c;哈哈。 昨…