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服务 ...
随机推荐
- .NET Core 中使用GBK GB2312编码报错的问题
错误描述 环境 dotnet core 2.1 2.2 dotnet core 3.1 dotnet core 5.0 现象 当代码中使用 System.Text.Encoding.GetEnco ...
- LlamaFS自组织文件管理器
LlamaFS是一个自组织文件管理器.它可以基于文件内容和修改时间等属性自动重命名和组织您的文件.它能让你不把时间花在对文件的复制.粘贴.重命名.拷贝.排序等简单操作上.有幸在Github上看到Lla ...
- kubenetes中的pod删除策略 级联删除与非级联删除
StatefulSet 有状态应用[有状态应用] 有状态:StatefulSet - 集群节点之间的关系. - 数据不完全一致. - 实例之间不对等的关系. - 依靠外部存储的应用. - 通过dns维 ...
- 微信iOS消息拦截插件教程-第一个tweak编译过程
-安装好theos框架之后,下面用一个简单的例子进行说明编译过程 -新建一个代码目录 -进入terminal,cd到刚才的目录中 1.进入目录 2.执行/opt/theos/bin/nic.pl 3. ...
- xv6 磁盘中断流程和启动时调度流程
首发公号:Rand_cs 本文讲述 xv6 中的一些细节流程,还有对之前文中遗留的问题做一些补充说明,主要有以下几个问题: 一次完整的磁盘中断流程 进入调度器后的详细流程 sched 函数中的条件判断 ...
- shell基础概述
1.0 编程的目的 计算机的发明,是为了用机器取代/解放人力,而编程的目的则是将人类的思想流程按照某种能够被计算机识别的表达方式传递给计算机,从而达到让计算机能够像人脑/电脑一样自动执行的效果. 编程 ...
- 蚁群算法及 TSP 问题上的应用
群智能(Swarm intelligence) 自然界动物群,称之为群. 群的特征: 相互作用的相邻个体的集合 个体的行为简单,既有竞争又有协作 智能化的集体行为(1+1>2): 个体间不仅能够 ...
- 一款.NET开源的i茅台自动预约小助手
前言 今天大姚给大家分享一款.NET开源.基于WPF实现的i茅台APP接口自动化每日自动预约(抢茅台)小助手:HyggeImaotai. 项目介绍 该项目通过接口自动化模拟i茅台APP实现每日自动预约 ...
- docker配置域名
先运行docker镜像 # 进入 docker 容器 mynginx 是容器名 docker exec -i -t mynginx /bin/bash #安装vim apt-get install v ...
- RPC和心跳机制
hadoop在节点间的内部通讯使用的是RPC,RPC协议把消息翻译成二进制字节流发送到远程节点,远程节点再通过反序列化把二进制流转成原始的信息. namenode与datanode之间的通信,jobt ...