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

news2024/11/24 12:47:10

文章目录

  • 前言
  • 直接运行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.coloradmin.cn/o/1361044.html

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

相关文章

数据库 补充 树,红黑树,b树,b+树

01.树 02.二叉树和二叉平衡树 03.平衡二叉树的恢复 将导致不平衡的结点称作被破坏者&#xff0c;破坏了结点的平衡的结点成为破坏者&#xff0c;经过调整可以让该树平衡的结点称为调整结点。 LL型&#xff1a; 以被破坏者的左孩子结点作为调整结点&#xff0c;对其进行右旋…

docker kingbase

docker kingbase run 命令 docker run -tid \ -e ENABLE_CIyes \ -e NEED_STARTyes \ -e DB_MODEoracle \ -e DB_USERkingbase \ -e DB_PASSWORD123456 \ --privileged \ -p 4321:54321 \ -v /home/admin/SoftWare/volume/kingbase/userdata/data:/home/kingbase/userdata/da…

【C语言】关闭socket需要包含的头文件

一、问题 linux系统&#xff0c;包含了头文件<sys/socket.h>&#xff0c; 警告 warning: implicit declaration of function ‘close’; did you mean ‘pclose’? [-Wimplicit-function-declaration] close(sockclient); ^~~~~ pclose 二、解决 在 Linux 系统下…

window 下载安装 Studio 3T

这里 我们先访问官网 https://studio3t.com/ 然后 他会弹出提示 如果您同意使用cookies和类似技术进行市场研究或广告目的&#xff0c;并希望获得额外功能&#xff0c;您可以点击“Accept all”按钮。 如果您不同意使用cookies和类似技术进行上述目的&#xff0c;您可以点击“…

C#编程-使用集合

使用集合 您学习了如何使用数组来有效地存储和操作相似类型额数据。但是,以下限制于数组的使用相关联: 您必须在声明时定义数组的大小。您必须编写代码以对数组执行标准操作,如排序。让我们思考一个示例。假设您想要存储在组织工作的五个雇员的姓名。您可以使用以下语句来声…

【大数据】Zookeeper 客户端的命令行操作

Zookeeper 客户端的命令行操作 1.显示某个路径下的所有节点&#xff1a;ls2.显示某个路径下的所有节点&#xff0c;以及当前节点的详细信息&#xff1a;ls23.创建节点&#xff1a;create4.创建临时节点&#xff1a;create -e5.创建顺序&#xff08;带编号&#xff09;节点&…

密码学:一文看懂初等数据加密一对称加密算法

文章目录 对称加密算法简述对称加密算法的由来对称加密算法的家谱数据加密标准-DES简述DES算法的消息传递模型DES算法的消息传递过程和Base64算法的消息传递模型的区别 算法的实现三重DES-DESede三重DES-DESede实现 高级数据加密标准一AES实现 国际数据加密标准-IDEA实现 基于口…

Spring面试篇

Spring面试篇 前置知识ApplicationContextInitializerApplicationListenerBeanFactoryBeanDefinitionBeanFactoryPostProcesssorAwareInitialzingBean&#xff0c;DisposableBeanBeanPostProcessor SpringBoot启动流程IOC容器初始化流程Bean生命周期Bean循环依赖解决 SpringMvc…

Burp Suite Intruder的4种攻击类型

这里写自定义目录标题 Burp Suite Intruder的4种攻击类型 Burp Suite Intruder的4种攻击类型

Spring 七种事务传播性介绍

作者&#xff1a;vivo 互联网服务器团队 - Zhou Shaobin 本文主要介绍了Spring事务传播性的相关知识。 Spring中定义了7种事务传播性&#xff1a; PROPAGATION_REQUIRED PROPAGATION_SUPPORTS PROPAGATION_MANDATORY PROPAGATION_REQUIRES_NEW PROPAGATION_NOT_SUPPORTED…

光明源智能:智慧厕所系统,打造智慧化科技智能生活

在这个科技飞速发展的时代&#xff0c;我们的生活正经历着一场全面的革命&#xff0c;而这场变革不仅仅局限于我们的工作和娱乐&#xff0c;甚至涉及我们生活中最私密的空间之一——卫生间。随着科技与卫生的巧妙融合&#xff0c;智慧厕所系统正日益成为一个引人注目的焦点。本…

构建高效秒杀系统的设计原理及注意事项

&#x1f604; 19年之后由于某些原因断更了三年&#xff0c;23年重新扬帆起航&#xff0c;推出更多优质博文&#xff0c;希望大家多多支持&#xff5e; &#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Mi…

5G-A,一根蓄满能量的弹簧

光阴转瞬&#xff0c;恍然间2024已经来到身边。经历了2023年全球AI技术大爆发&#xff0c;以及智能汽车、虚拟现实、自主科技等诸多领域取得关键进展。想必大家希望知道在新一年中有哪些值得期待的科技增长空间。 如果是这样&#xff0c;那么不妨将目光投向5G-A。 与其他科技领…

轻松入门:Anaconda 在 PyCharm 中的配置与应用指南

1 Anaconda Anaconda 和 Conda 是两个相关但不同的概念。 Anaconda 是一个免费且开源的发行版&#xff0c;包含了 Python 和 R 语言的数据科学和机器学习相关的众多包&#xff0c;它包括 Conda、Python、Jupyter Notebook 等多个科学计算和数据科学中常用的应用。 Anaconda 通过…

unity中0GC优化方案《zstring》

文章目录 序言简介GC带来的问题性能瓶颈玩家体验受损 使用方式 序言 游戏开发秉承遇到好东西要分享&#xff0c;下面介绍zstring&#xff0c;感谢作者开源无私奉献 源码地址&#xff1a;https://github.com/871041532/zstring 简介 GC带来的问题 性能瓶颈 GC暂停主线程执行…

你珍藏的那个表情包女孩,现在滤镜碎了一地。

♥ 为方便您进行讨论和分享&#xff0c;同时也为能带给您不一样的参与感。请您在阅读本文之前&#xff0c;点击一下“关注”&#xff0c;非常感谢您的支持&#xff01; 文|猴哥聊娱乐 编辑|侯欢庭 七年前&#xff0c;一个年仅三岁的小女孩以其无邪的表情包风靡网络&#xff0…

科锐16位汇编学习笔记 03 汇编指令

指令种类 数据传送指令算数运算类指令位操作类指令串操作类指令控制转移类指令处理器控制类指令 数据传送类指令 传送类指令不影响标志位&#xff0c;**除了标志位传送指令外。** 传送指令MOV&#xff08;move&#xff09; 说明 ​ 把一个字节或字的操作数从源地址传送至…

安全与认证Week3 Tutorial+历年题补充

目录 1) 什么是重放攻击? 2)什么是Kerberos系统?它提供什么安全服务? 3)服务器验证客户端身份的一种简单方法是要求提供密码。在Kerberos中不使用这种身份验证&#xff0c;为什么?Kerberos如何对服务器和客户机进行身份验证? 4) Kerberos的四个要求是什么?Kerberos系…

Python IDE Pycharm服务器配置方法并结合内网穿透工具实现远程开发

文章目录 一、前期准备1. 检查IDE版本是否支持2. 服务器需要开通SSH服务 二、Pycharm本地链接服务器测试1. 配置服务器python解释器 三、使用内网穿透实现异地链接服务器开发1. 服务器安装Cpolar2. 创建远程连接公网地址 四、使用固定TCP地址远程开发 本文主要介绍如何使用Pych…

位移贴图还原电影3D角色

在线工具推荐&#xff1a; 3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎 位移贴图&#xff08;Displacement Map&#xff09;在电影制作中是一…