首页 星云 工具 资源 星选 资讯 热门工具
:

PDF转图片 完全免费 小红书视频下载 无水印 抖音视频下载 无水印 数字星空

C# 通过反射(Reflection)调用不同名泛型方法

编程知识
2024年07月27日 14:02

概述

由于工作需要,需要通过数据类型和方法名控制方法走向
用到的数据类型有8种(string,Int16,Int32,Int64,Boolean,Byte,Single,Double)
读取的方法(参数一致,但是数据不同的泛型方法,返回值也是泛型)暂时只有11种,但肯定的是,后续一定会增加

原本计划排列组合,写个88行代码,但是总觉得重复代码过多,且后续维护极其繁琐
例如:新增一个读取方法,需要额外新增8行数据类型选择代码,繁琐暂且不说,主要是容易出现纰漏

网络上一翻搜寻,找到了反射,完美解决了我的问题,现在想把这个反射分享给大家:

排列组合

没错,我最开始就是排列组合


int datatype = default(int) ; // 决定值类型
int GetType = default(int) ; // 决定通过什么方法读取

//类型选择
switch (datatype)
{
    case 2: res[0] += "'" + Convert.ToString(ReadString(dataaddress , datalen , gettype)) + "',"; break;
    case 4: res[0] += Convert.ToString(ReadInt(dataaddress , datalen , gettype)) + ","; break;
    case 6: res[0] += "'" + Convert.ToString(ReadString(dataaddress , datalen , gettype)) + "',"; break;
    case 7: res[0] += Convert.ToString(ReadUshort(dataaddress , datalen , gettype)) + ","; break;
    case 8: res[0] += Convert.ToString(ReadUint(dataaddress , datalen , gettype)) + ","; break;
    case 9: res[0] += Convert.ToString(ReadULong(dataaddress , datalen , gettype)) + ","; break;
    case 10: res[0] += Convert.ToString(ReadInt(dataaddress , datalen , gettype)) + ","; break;
    case 11: res[0] += Convert.ToString(ReadShort(dataaddress , datalen , gettype)) + ","; break;
    case 12: res[0] += Convert.ToString(ReadByte(dataaddress , datalen , gettype)) + ","; break;
    case 13: res[0] += Convert.ToString(ReadFloat(dataaddress , datalen , gettype)) + ","; break;
    case 14: res[0] += Convert.ToString(ReadDouble(dataaddress , datalen , gettype)) + ","; break;
    case 15: res[0] += Convert.ToString(ReadDouble(dataaddress , datalen , gettype)) + ","; break;
    case 20: res[0] += Convert.ToString(ReadBool(dataaddress , datalen , gettype)).ToLower() + ","; break;
    case 31: res[0] += Convert.ToString(ReadLong(dataaddress , datalen , gettype)) + ","; break;
    default: res[0] += Convert.ToString(ReadUshort(dataaddress , datalen , gettype)) + ","; break;
}
//方法选择
//string
public string ReadString(string StartAddress , int Length , int GetType)
{
    switch (GetType)
    {
        case 1: return ModbusTcpRead<string>(StartAddress , Length);
        case 2: return ModbusRtuRead<string>(StartAddress , Length);
        case 3: return ModbusRtuOverTcpRead<string>(StartAddress , Length);
        case 5: return InovanceTcpNetRead<string>(StartAddress , Length);
        case 6: return KeyenceMcNetRead<string>(StartAddress , Length);
        case 7: return MelsecMcNetRead<string>(StartAddress , Length);
        case 8: return OmronFinsNetRead<string>(StartAddress , Length);
        case 9: return PanasonicMcNetRead<string>(StartAddress , Length);
        case 10: return SiemensS7NetRead<string>(StartAddress , Length);
        case 11: return MelsecFxSerialOverTcpRead<string>(StartAddress , Length);
        case 12: return KeyenceMcAsciiNetRead<string>(StartAddress , Length);
        default: return ModbusTcpRead<string>(StartAddress , Length);
    }
}
//Bool
public bool ReadBool(string StartAddress , int Length , int GetType)
{
    switch (GetType)
    {
        case 1: return ModbusTcpRead<bool>(StartAddress , Length);
        case 2: return ModbusRtuRead<bool>(StartAddress , Length);
        case 3: return ModbusRtuOverTcpRead<bool>(StartAddress , Length);
        case 5: return InovanceTcpNetRead<bool>(StartAddress , Length);
        case 6: return KeyenceMcNetRead<bool>(StartAddress , Length);
        case 7: return MelsecMcNetRead<bool>(StartAddress , Length);
        case 8: return OmronFinsNetRead<bool>(StartAddress , Length);
        case 9: return PanasonicMcNetRead<bool>(StartAddress , Length);
        case 10: return SiemensS7NetRead<bool>(StartAddress , Length);
        case 11: return MelsecFxSerialOverTcpRead<bool>(StartAddress , Length);
        case 12: return KeyenceMcAsciiNetRead<bool>(StartAddress , Length);
        default: return ModbusTcpRead<bool>(StartAddress , Length);
    }
}
......(就不全部列出来了,排列组合,懂得吧?)

或许你发现了什么异常,感觉我这么写不太对,应该先控制方法,在控制值类型,但,没区别,还是排列组合,只不过分散了而已

以上代码也不难看出,重复代码非常多,几乎就是copy一份,然后改一下泛型传入

所以我在想,能不能吧参数转换成泛型填入,然后显然不行,后来找到了反射这个法宝

反射(正片开始)

int datatype = default(int) ; // 决定值类型
int GetType = default(int) ; // 决定通过什么方法读取

//方法名
string methodName = "ModbusTcpRead";
switch (gettype)
{
    case 1: methodName = "ModbusTcpRead"; break;
    case 2: methodName = "ModbusRtuRead"; break;
    case 3: methodName = "ModbusRtuOverTcpRead"; break;
    case 5: methodName = "InovanceTcpNetRead"; break;
    case 6: methodName = "KeyenceMcNetRead"; break;
    case 7: methodName = "MelsecMcNetRead"; break;
    case 8: methodName = "OmronFinsNetRead"; break;
    case 9: methodName = "PanasonicMcNetRead"; break;
    case 10: methodName = "SiemensS7NetRead"; break;
    case 11: methodName = "MelsecFxSerialOverTcpRead"; break;
    case 12: methodName = "KeyenceMcAsciiNetRead"; break;
    default: methodName = "ModbusTcpRead"; break;
}
//数据值类型
string type = "System.Int32";
switch (datatype)
{
    case 2: type = "System.String"; break;
    case 4: type = "System.Int32"; break; 
    case 6: type = "System.String"; break;
    case 7: type = "System.UInt16"; break; 
    case 8: type = "System.UInt32"; break; 
    case 9: type = "System.UInt64"; break;
    case 10: type = "System.Int32"; break;
    case 11: type = "System.Int16"; break;
    case 12: type = "System.Byte"; break;
    case 13: type = "System.Single"; break;//float
    case 14: type = "System.Double"; break;
    case 15: type = "System.Double"; break;
    case 20: type = "System.Boolean"; break;
    case 31: type = "System.Int64"; break;
    default: type = "System.UInt16"; break;
}
MethodInfo method = typeof(PLCOper).GetMethod(methodName , BindingFlags.Instance | BindingFlags.Public);
MethodInfo genericMethod = method.MakeGenericMethod(Type.GetType(type , false));
object result = genericMethod.Invoke(this , new object[] { dataaddress , datalen });

//这里有几点要提醒
//1、typeof(PLCOper) 括号里的类名必须是调用方法的父类名
//2、GetMethod 第二个参数,前者用于过滤方法的属性,比如是静态还是非静态,我方法全是非静态,所以需要BindingFlags.Instance 参数
//3、Invoke 第一个参数,如果调用静态方法,传入null就好,实例内的方法,需要传入this
//4、Invoke 第二个参数,是方法的入参

是不是简洁非常多?(看起来没区别或许是因为排列组合我没全部写出来?)

以后新增方法名也只需要在这里改一次就可以了

非常完美!

结束

感谢看到这里。

From:https://www.cnblogs.com/HookDing/p/18326960
本文地址: http://www.shuzixingkong.net/article/481
0评论
提交 加载更多评论
其他文章 《Programming from the Ground Up》阅读笔记:p88-p94
《Programming from the Ground Up》学习第5天,p88-p94总结,总计7页。 一、技术总结 1.touppercase.s #PURPOSE: This program converts an input file #to an output file with all
《Programming from the Ground Up》阅读笔记:p88-p94
一款.NET开源、跨平台的DASH/HLS/MSS下载工具
前言 今天大姚给大家分享一款.NET开源(MIT License)、免费、跨平台的DASH/HLS/MSS下载工具,并且支持点播和直播(DASH/HLS)的内容下载:N_m3u8DL-RE。 网络流媒体传输协议介绍 DASH DASH是一种基于HTTP的自适应流媒体网络传输协议,它允许流媒体内容以多
一款.NET开源、跨平台的DASH/HLS/MSS下载工具 一款.NET开源、跨平台的DASH/HLS/MSS下载工具 一款.NET开源、跨平台的DASH/HLS/MSS下载工具
不是,大哥,咱这小门小户的,别搞我CDN流量啊
分享是最有效的学习方式。 博客:https://blog.ktdaddy.com/ 最近遇上事儿了,老猫的小小博客网站【程序员老猫的博客】被人盗刷CDN流量了。开始的时候收到了欠费的短信也没有怎么去重视。虽然说费用没有多少,但是也是一个教训。 博客从最初地搭建到现在确实也经过好几年了,天真地以为确实
不是,大哥,咱这小门小户的,别搞我CDN流量啊 不是,大哥,咱这小门小户的,别搞我CDN流量啊 不是,大哥,咱这小门小户的,别搞我CDN流量啊
业务场景---Token无感刷新
业务场景描述 假设用户正在填写一个复杂的表单,由于表单内容繁多,用户花费了很长时间才填完。这时,如果Token已经过期,系统会让用户重新登录,这种体验显然是非常糟糕的。为了避免这种情况,我们需要在Token即将过期或已经过期时,自动刷新Token,而不影响用户正在进行的操作。 技术实现思路 一、准备
超级猫超级签名分发平台前台SQL注入漏洞+前台任意文件删除漏洞+前台远程文件写入漏洞+前台任意文件读取漏洞+前台任意命令执行漏洞
超级猫超级签名分发平台前台SQL注入漏洞+前台任意文件删除漏洞+前台远程文件写入漏洞+前台任意文件读取漏洞+前台任意命令执行漏洞
超级猫超级签名分发平台前台SQL注入漏洞+前台任意文件删除漏洞+前台远程文件写入漏洞+前台任意文件读取漏洞+前台任意命令执行漏洞 超级猫超级签名分发平台前台SQL注入漏洞+前台任意文件删除漏洞+前台远程文件写入漏洞+前台任意文件读取漏洞+前台任意命令执行漏洞 超级猫超级签名分发平台前台SQL注入漏洞+前台任意文件删除漏洞+前台远程文件写入漏洞+前台任意文件读取漏洞+前台任意命令执行漏洞
ComfyUI插件:ComfyUI Impact 节点(一)
前言: 学习ComfyUI是一场持久战,而 ComfyUI Impact 是一个庞大的模块节点库,内置许多非常实用且强大的功能节点 ,例如检测器、细节强化器、预览桥、通配符、Hook、图片发送器、图片接收器等等。通过这些节点的组合运用,我们可以实现的工作有很多,例如自动人脸检测和优化修复、区域增强、
ComfyUI插件:ComfyUI Impact 节点(一) ComfyUI插件:ComfyUI Impact 节点(一) ComfyUI插件:ComfyUI Impact 节点(一)
Spring 常用的三种拦截器详解
在开发过程中,我们常常使用到拦截器来处理一些逻辑。最常用的三种拦截器分别是 AOP、 Interceptor 、 Filter,但其实很多人并不知道什么时候用AOP,什么时候用Interceptor,什么时候用Filter,也不知道其拦截顺序,内部原理。今天我们详细介绍一下这三种拦截器。
Spring 常用的三种拦截器详解 Spring 常用的三种拦截器详解
带你学习通过GitHub Actions如何快速构建和部署你自己的项目,打造一条属于自己的流水线
本文主要讲解通过github的actions来对我们项目进行ci/cd System.out.println(&quot;原文地址:https://www.cnblogs.com/ancold/p/18327097&quot;); 一、actions简介 GitHub Actions 是一种持续集成
带你学习通过GitHub Actions如何快速构建和部署你自己的项目,打造一条属于自己的流水线 带你学习通过GitHub Actions如何快速构建和部署你自己的项目,打造一条属于自己的流水线 带你学习通过GitHub Actions如何快速构建和部署你自己的项目,打造一条属于自己的流水线