概述

由于工作需要,需要通过数据类型和方法名控制方法走向

用到的数据类型有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)调用不同名泛型方法的更多相关文章

  1. 代理(Proxy)和反射(Reflection)

    前面的话 ES5和ES6致力于为开发者提供JS已有却不可调用的功能.例如在ES5出现以前,JS环境中的对象包含许多不可枚举和不可写的属性,但开发者不能定义自己的不可枚举或不可写属性,于是ES5引入了O ...

  2. C# 反射Reflection——反射反射程序员的快乐

    一.什么是反射 反射Reflection:System.Reflection,是.Net Framework提供的一个帮助类库,可以读取并使用metadata. 反射是无处不在的,MVC-Asp.Ne ...

  3. [.net 面向对象程序设计进阶] (21) 反射(Reflection)(下)设计模式中利用反射解耦

    [.net 面向对象程序设计进阶] (21) 反射(Reflection)(下)设计模式中利用反射解耦 本节导读:上篇文章简单介绍了.NET面向对象中一个重要的技术反射的基本应用,它可以让我们动态的调 ...

  4. [.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程

    [.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程 本节导读:本节主要介绍什么是.NET反射特性,.NET反射能为我们做些什么,最后介绍几种常用的 ...

  5. [整理]C#反射(Reflection)详解

    本人理解: 装配件:Assembly(程序集) 晚绑定:后期绑定 MSDN:反射(C# 编程指南) -----------------原文如下-------- 1. 什么是反射2. 命名空间与装配件的 ...

  6. C# 利用反射动态调用类成员

    用反射动态调用类成员,需要Type类的一个方法:InvokeMember.对该方法的声明如下(摘抄于MSDN): publicobject InvokeMember(    string name, ...

  7. 反射Reflection创建

    step one:(找入口) using System.Reflection; //引用需要用到的命名空间 做任何事都要有开始的地方,不例外,反射也要先找到反射的入口,举个栗子: Assembly a ...

  8. C#动态调用泛型类、泛型方法

    在制作一个批量序列化工具时遇到了如下问题,在此记录一下,仅供参考. 主程序加载另一个程序集,将其中的所有类取出,然后对这些类分别调用泛型类或泛型方法.控制台程序解决方案如下: Main工程:提供Wor ...

  9. Golang 反射reflection

    反射reflection 反射可大大提高程序的灵活性,使得interface{}有更大的发挥余地 反射使用TypeOf和ValueOf函数从接口中获取目标对象信息 反射会将匿名字段作为独立字段(匿名字 ...

  10. 采用异步来实现重新连接服务器或者重新启动服务 C#中类的属性的获取 SignalR2简易数据看板演示 C#动态调用泛型类、泛型方法 asp .net core Get raw request. 从壹开始前后端分离[.NetCore 不定期更新] 38 ║自动初始化数据库

    采用异步来实现重新连接服务器或者重新启动服务 开启异步监听,不会导致主线程的堵塞,在服务异常断开后一直检测重新连接服务,成功连接服务后通知各个注册的客户端! #region 检测断线并重连OPC服务 ...

随机推荐

  1. WPF 设置第二次打开程序直接弹出第一次打开的程序

    激活已经打开窗口函数[DllImport("user32.dll")]private static extern bool SetForegroundWindow(IntPtr h ...

  2. Easysearch 内核完善之 OOM 内存溢出优化案例一则

    最近某客户在使用 Easysearch 做聚合时,报出 OOM 导致掉节点的问题,当时直接让客户试着调整 indices.breaker.request.limit ,但是不起作用,于是又看了下 Ea ...

  3. Vue学习:20.综合案例-商品列表

    学而时用之,方能融会贯通! 实例:商品列表 实现功能 要求表格组件支持动态数据渲染.自定义表头和主体.标签组件需要双击显示输入框并获得焦点,可以编辑标签信息. 思路 首先是表格组件,动态渲染需要使用组 ...

  4. Python3.7+Robot Framework+RIDE1.7.4.1安装使用教程

    一.解惑:Robot Framewprk今天我们聊一聊,Robot Framework被众多测试工程师误会多年的秘密.今天我们一起来揭秘一下,最近经常在各大群里听到许多同行,在拿Robot Frame ...

  5. 两个Excel表格核对 excel表格中# DIV/0 核对两个表格的差异,合并运算VS高级筛选

    两个Excel表格核对   excel表格中# DIV/0 核对两个表格的差异,合并运算VS高级筛选 1.两列顺序一样的数据核对 方法1:加一个辅助列,=B2=C2 结果为FALSE的就是不相同的 方 ...

  6. spring boot jpa 进行通用多条件动态查询和更新 接口

    原因: jpa 没有类似于mybatis的那种 拼接sql的方式 想动态更新 需要使用 CriteriaUpdate的方式 去一直拼接,其实大多数场景只要传入一个非空实体类,去动态拼接sql 1.定义 ...

  7. Vue3 中的 v-bind 指令:你不知道的那些工作原理

    前言 v-bind指令想必大家都不陌生,并且都知道他支持各种写法,比如<div v-bind:title="title">.<div :title="t ...

  8. C# SM2算法 加密,解密,签名,验签

    最近时间在整SM2算法,在网上看到不少代码,基本都是使用BouncyCastle库,现在这个版本算比较好的拿来分享给大家. 首先引入包 Portable.BouncyCastle 完整代码见Gitee ...

  9. FEDORA34 安装CUDA11.3

    FEDORA34 安装CUDA11.3 首先确保能装上最新的显卡驱动.  FEDORA显卡驱动安装 然后去官网下fedora对应的.run安装文件.运行安装, 但不要选装驱动. 完成后加环境变量: # ...

  10. ClickHouse介绍(二)MergeTree引擎

    MergeTree引擎 ClickHouse中有多种表引擎,包括MergeTree.外部存储.内存.文件.接口等,6大类,20多种表引擎.其中最强大的当属MergeTree(及其同一家族中)引擎.我们 ...