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实战的一些问题。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【SpringCloud】之远程消费(进阶使用)

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是君易--鑨&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的博客专栏《SpringCloud开发之远程消费》。&#x1f3af;&a…

python画图工具总结

一、python工具 python运行工具&#xff1a;Anaconda3 Anaconda3运行模式&#xff1a;jupyter notebook 操作系统&#xff1a;window11 二、折线图 from matplotlib import pyplot import matplotlib.pyplot as plt from math import sqrt import pandas as pd from matplot…

ffmpeg.c(4.3.1)源码剖析

文章目录 前言一、FFmpeg 源码结构图二、ffmpeg.h 头文件详解三、main 函数主要流程分析四、ffmpeg_parse_options1、命令行例子①、解析命令行 split_commandline()②、parse_optgroup()③、MATCH_PER_XXX_OPT() 2、vf 选项解析①、filters②、vf 术语③、avfilter_graph_pars…

【LeetCode每日一题】2807. 在链表中插入最大公约数(模拟+求最大公约数的6中写法)

2024-1-6 文章目录 [2807. 在链表中插入最大公约数](https://leetcode.cn/problems/insert-greatest-common-divisors-in-linked-list/)思路&#xff1a;模拟求最大公约数的几种方法&#xff1a; 1.暴力枚举法2.辗转相除法3.辗转相除法 ---递归调用4.辗转相除法 ---递归调用---…

微服务注册中的负载均衡

背景 随着互联网行业的发展&#xff0c;对服务的要求也越来越高&#xff0c;服务架构也从单体架构逐渐演变为现在流行的微服务架构。这些架构之间有怎样的差别呢&#xff1f; 单体架构&#xff1a;简单方便&#xff0c;高度耦合&#xff0c;扩展性差&#xff0c;适合小型项目。…

【计算机毕业设计】SSM在线化妆品网站

项目介绍 本项目为前后台项目&#xff0c;前台为普通用户登录&#xff0c;后台为管理员登录&#xff1b; 管理员角色包含以下功能&#xff1a; 管理员登录,分类管理,产品管理,用户管理,订单管理等功能。 用户角色包含以下功能&#xff1a; 提交订单,用户登录,用户首页,查看…

MySQL数据库期末知识点总结(复习版)

一、数据库基本知识 数据库中的数据有什么特点 1、数据是按某种结构组织的 2、数据有整体性、共享性和较高的独立性 数据管理技术经历了哪三个阶段 1、手工管理 2、文件管理 3、数据库管理 数据库管理系统的主要功能有哪些 数据库管理系统的主要功能包括数据定义、数据…

欧科云链研究院:奔赴2024,Web3与AI共振引爆数字时代潘多拉魔盒

出品&#xff5c;欧科云链研究院 2024年&#xff0c;Web3与AI两个数字科技的巅峰碰撞&#xff0c;欧科云链研究院探索AI与Web3的技术融合&#xff0c;与澎湃科技联合发布2024年展望&#xff0c;原标题为《2024年展望&#xff1a;Web3与AI共振引爆可信数字社会》&#xff0c;共…

Mybatis-Mapper代理开发

Mapper代理开发 目的使用Mapper代理方式入门1.定义与SQL映射文件同名的Mapper接口&#xff0c;并且将Mapper接口和SQL映射文件放置在同一目录下首先新建一个Mapper接口编译mybatis-demo更改sql映射文件路径 2.设置SQL映射文件的namespace属性为Mapper接口全限定名3.在Mapper 接…

数据在内存中的存储之大小端

今天也是努力学编程&#xff0c;敲代码的一天&#xff01; 1.什么是大小端 其实超过一个字节的数据在内存中存储的时候&#xff0c;就有存储顺序的问题&#xff0c;按照不同的存储顺序&#xff0c;我们分为大端字节序 存储和小端字节序存储&#xff0c;下面是具体的概念: &…

吉时利2601A数字源表Keithley 2601A

吉时利2601A源测量单元&#xff08;SMU&#xff09;&#xff0c;也被称为源表&#xff0c;是一种高性能的仪器&#xff0c;能够提供100毫伏至40伏的电压范围&#xff0c;以及100纳至10安的电流范围。这种仪器能够提供的功率高达40.4瓦&#xff0c;使其在台式I-V表征工具或多通道…

如何充值GPT会员账号?

详情点击链接&#xff1a;如何充值GPT会员账号&#xff1f; 一OpenAI 1.最新大模型GPT-4 Turbo 2.最新发布的高级数据分析&#xff0c;AI画图&#xff0c;图像识别&#xff0c;文档API 3.GPT Store 4.从0到1创建自己的GPT应用 5. 模型Gemini以及大模型Claude2二定制自己的…

TYPE-C接口取电芯片介绍和应用场景

随着科技的发展&#xff0c;USB PDTYPE-C已经成为越来越多设备的充电接口。而在这一领域中&#xff0c;LDR6328Q PD取电芯片作为设备端协议IC芯片&#xff0c;扮演着至关重要的角色。本文将详细介绍LDR6328Q PD取电芯片的工作原理、应用场景以及选型要点。 一、工作原理 LDR63…

2024年【危险化学品生产单位主要负责人】复审模拟考试及危险化学品生产单位主要负责人作业模拟考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年危险化学品生产单位主要负责人复审模拟考试为正在备考危险化学品生产单位主要负责人操作证的学员准备的理论考试专题&#xff0c;每个月更新的危险化学品生产单位主要负责人作业模拟考试祝您顺利通过危险化学品…

Beauty algorithm(六)大眼

前几篇主要介绍了唇妆、腮红、眼影、眉形渲染,它们都有一个共同点,关键点只需要检测一次,并且在获得目标区域融合渲染时,只是对像素点加权操作,处理速度快。而对于美颜,如大眼、缩鼻、缩下巴等操作,会产生局部形变,造成关键点移位。因此每次缩放后都要重新检测关键点,…

C++之STL库简介

目录 一、STL&#xff08;Standard Template Library&#xff0c;标准模板库&#xff09; 二、容器&#xff08;Containers&#xff09; 1.vector&#xff08;动态数组&#xff09; 2.list&#xff08;双向链表&#xff09; 3.deque&#xff08;双端队列&#xff09; 4.st…

【十】【C语言\动态规划】376. 摆动序列、673. 最长递增子序列的个数、646. 最长数对链,三道题目深度解析

动态规划 动态规划就像是解决问题的一种策略&#xff0c;它可以帮助我们更高效地找到问题的解决方案。这个策略的核心思想就是将问题分解为一系列的小问题&#xff0c;并将每个小问题的解保存起来。这样&#xff0c;当我们需要解决原始问题的时候&#xff0c;我们就可以直接利…

JS的防抖和节流

目录 防抖 搜索框带来的问题 实现的思路 案例 封装防抖函数 节流 滚动条加载带来的问题 实现的思路 案例 封装节流函数 防抖 搜索框带来的问题 需求&#xff1a;根据输入框内容来请求数据 <!DOCTYPE html> <html lang"en"> <head><…

基于ElementUI封装的下拉树选择可搜索单选多选清空功能

效果&#xff1a; 组件代码 /*** 树形下拉选择组件&#xff0c;下拉框展示树形结构&#xff0c;提供选择某节点功能&#xff0c;方便其他模块调用* author wy* date 2024-01-03 * 调用示例&#xff1a;* <tree-select * :height"400" // 下拉框中树形高度* …

mysql原理--事务

1.事务的起源 对于大部分程序员来说&#xff0c;他们的任务就是把现实世界的业务场景映射到数据库世界。比如银行为了存储人们的账户信息会建立一个 account 表&#xff1a; CREATE TABLE account (id INT NOT NULL AUTO_INCREMENT COMMENT 自增id,name VARCHAR(100) COMMENT …