C# 通过反射(Reflection)调用不同名泛型方法
概述
由于工作需要,需要通过数据类型和方法名控制方法走向
用到的数据类型有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 第二个参数,是方法的入参
是不是简洁非常多?(看起来没区别或许是因为排列组合我没全部写出来?)
以后新增方法名也只需要在这里改一次就可以了
非常完美!
结束
感谢看到这里。
C# 通过反射(Reflection)调用不同名泛型方法的更多相关文章
- 代理(Proxy)和反射(Reflection)
前面的话 ES5和ES6致力于为开发者提供JS已有却不可调用的功能.例如在ES5出现以前,JS环境中的对象包含许多不可枚举和不可写的属性,但开发者不能定义自己的不可枚举或不可写属性,于是ES5引入了O ...
- C# 反射Reflection——反射反射程序员的快乐
一.什么是反射 反射Reflection:System.Reflection,是.Net Framework提供的一个帮助类库,可以读取并使用metadata. 反射是无处不在的,MVC-Asp.Ne ...
- [.net 面向对象程序设计进阶] (21) 反射(Reflection)(下)设计模式中利用反射解耦
[.net 面向对象程序设计进阶] (21) 反射(Reflection)(下)设计模式中利用反射解耦 本节导读:上篇文章简单介绍了.NET面向对象中一个重要的技术反射的基本应用,它可以让我们动态的调 ...
- [.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程
[.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程 本节导读:本节主要介绍什么是.NET反射特性,.NET反射能为我们做些什么,最后介绍几种常用的 ...
- [整理]C#反射(Reflection)详解
本人理解: 装配件:Assembly(程序集) 晚绑定:后期绑定 MSDN:反射(C# 编程指南) -----------------原文如下-------- 1. 什么是反射2. 命名空间与装配件的 ...
- C# 利用反射动态调用类成员
用反射动态调用类成员,需要Type类的一个方法:InvokeMember.对该方法的声明如下(摘抄于MSDN): publicobject InvokeMember( string name, ...
- 反射Reflection创建
step one:(找入口) using System.Reflection; //引用需要用到的命名空间 做任何事都要有开始的地方,不例外,反射也要先找到反射的入口,举个栗子: Assembly a ...
- C#动态调用泛型类、泛型方法
在制作一个批量序列化工具时遇到了如下问题,在此记录一下,仅供参考. 主程序加载另一个程序集,将其中的所有类取出,然后对这些类分别调用泛型类或泛型方法.控制台程序解决方案如下: Main工程:提供Wor ...
- Golang 反射reflection
反射reflection 反射可大大提高程序的灵活性,使得interface{}有更大的发挥余地 反射使用TypeOf和ValueOf函数从接口中获取目标对象信息 反射会将匿名字段作为独立字段(匿名字 ...
- 采用异步来实现重新连接服务器或者重新启动服务 C#中类的属性的获取 SignalR2简易数据看板演示 C#动态调用泛型类、泛型方法 asp .net core Get raw request. 从壹开始前后端分离[.NetCore 不定期更新] 38 ║自动初始化数据库
采用异步来实现重新连接服务器或者重新启动服务 开启异步监听,不会导致主线程的堵塞,在服务异常断开后一直检测重新连接服务,成功连接服务后通知各个注册的客户端! #region 检测断线并重连OPC服务 ...
随机推荐
- 【2023全网最全最火】Selenium WebDriver教程(建议收藏)
在本教程中,我将向您介绍 Selenium Webdriver,它是当今市场上使用最广泛的自动化测试框架.它是开源的,可与所有著名的编程语言(如Java.Python.C#.Ruby.Perl等)一起 ...
- 002. git 分支管理
git分支 git分支,从本质上来讲仅仅是指向提交对象的可变指针,在这一点上与svn是有着本质区别,svn的分支实际就是个目录而已. git默认分支名字是 master,在多次提交操作后,你其实已经有 ...
- edge 书签栏 收藏夹栏 字体大小
WIN10中,edge收藏夹栏字体太大,如果收藏数目多,得多翻好几页. 解决方法: 地址栏中输入: edge://flags/#edge-pc-ui-integration Enable Window ...
- 太卷了,史上最简单的监控系统 catpaw 简介
指标监控的痛点 当下比较流行的监控系统,比如 Prometheus.Nightingale.VictoriaMetrics,都是基于数值型指标的监控系统,这类监控系统的痛点在于:告警的时候只能拿到异常 ...
- 用ESP8266-NodeMCU开发板显示一下我的QQ头像
诶,说好的自己写esp8266的开发板固件的我回来了. 20年说好的,今天回来还愿了 ESP8266串口WiFi模块 - WiFi杀手 今天我们把OLED显示屏也接上,我此次买的是4脚的OLED(12 ...
- 数据库阻塞查询语句 SQL SERVER
--查询CPU占用最高的SQL语句 SELECT total_worker_time/execution_count AS avg_cpu_cost, plan_handle, execution_c ...
- Atcoder Beginner Contest 324 F Beautiful Path 题解-分数规划
为了更好的阅读体验,请点击这里 分数规划小技巧:尽可能将式子写成存在某种取值,使得不等式成立的形式. 不然可能需要绕几个弯才能想出来. 题目链接 题目大意:给出一个 DAG,每条边有一个 \(b_i, ...
- python重拾第五天-常用模块学习
本节大纲: 模块介绍 time &datetime模块 random os sys shutil json & picle shelve xml处理 yaml处理 configpars ...
- Ubuntu中安装最新 Node.js 和 npm
背景 为了安装GNU QEMU Eclipse,需要安装比较新的nodejs $ npm install --global xpm@latest ▌ ╢░░░░░░░░░░░░░░░░░░░░░░░░ ...
- 【论文阅读】Causal Imitative Model for Autonomous Driving
Sensor/组织: EPFL Sharif University of Technology Status: Finished Summary: 看看框架图就行.高效缓解因果混淆问题,将因果作为学习 ...