概述

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

用到的数据类型有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. 转 [golang]为什么Response.Body需要被关闭

    Body io.ReadCloser       The http Client and Transport guarantee that Body is always non-nil, even o ...

  2. Android桌面Launcher源码浅析

    在Android启动过程-万字长文(Android14)中介绍了Android系统的启动过程,本篇文章将继续介绍桌面应用Launcher. 一.Launcher介绍 在Android启动过程-万字长文 ...

  3. Pyinstaller打包exe的反编译——LitCTF 2024(公开赛道)ezpython!!!!!

    这个工具折磨了我很久,搭配题目记录一下... 题目 Die 打包工具: PyInstaller 建议下载GitHub的:GitHub - extremecoders-re/pyinstxtractor ...

  4. 阿里云入选Gartner「边缘分发平台市场指南」代表厂商

    近日,全球技术研究与咨询机构Gartner首次发布边缘分发平台市场指南报告<Market Guide for Edge Distribution Platforms>,阿里云凭借内容分发网 ...

  5. uniapp 返回顶部

    <template> <view> <view class="btn" @tap="toTop" :style="{'d ...

  6. php分组查询和聚合函数 数据显示的顺序

      // 分组查询和聚合函数         // 分组查询 : 将指定字段中的数据,按照不同的具体数值,进行分组         //           数据相同的分在一个分组中          ...

  7. Java中可以用的大数据推荐算法

    在Java中实现大数据推荐算法时,通常会使用一些开源的机器学习库,如Apache Mahout.Weka.DL4J(DeepLearning4j,用于深度学习)或者Spark MLlib(用于在Spa ...

  8. ncnn的blob_vkallocator、workspace_vkallocator、staging_vkallocator区别

    ncnn::Extractor中有三个成员函数: void set_blob_vkallocator(VkAllocator* allocator); void set_workspace_vkall ...

  9. 夜莺监控(Nightingale)上线内置指标功能

    Prometheus 生态里如果要查询数据,需要编写 promql,对于普通用户来说,门槛有点高.通常有两种解法,一个是通过 AI 的手段做翻译,你用大白话跟 AI 提出你的诉求,让 AI 帮你写 p ...

  10. linux查看redis安装路径

    ## linux查看redis安装路径 redis-cli -h 127.0.0.1 -p 6379redis-cli monitor > redis2.log /usr/local/redis ...