概述

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

用到的数据类型有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. 基于 Kubernetes 的 CICD 基础设施即代码

    在上一篇基于 Kubernetes 的基础设施即代码一文中,我概要地介绍了基于 Kubernetes 的 .NET Core 微服务和 CI/CD 动手实践工作坊使用的基础设施是如何使用代码描述的,以 ...

  2. 如何判断7z压缩文件格式

    如果压缩文件的后缀不是7z,那么如何如何判断文件格式呢?那就是通过文件头判断. 7z文件头前6位,固定是:377ABCAF271C,其中前两位37.7A分别是"7""z& ...

  3. 003. git标签

    git标签 标签用于记录详细修改内容,为后续使用提供帮助. 也方便快速的回滚. 每一次提交[commit]都可以打一个tag标签. 测试阶段标签规则: 以 0.01 0.02版本为主 正式上线标签规则 ...

  4. uniapp 富文本图片100%显示

    下面的这个方法是在百度上找的,但是老是报错,一直没找到原因,索性自己就挨个检查了下,发现在过滤之前需要对传过来的值进行检测,是字符串才能让这个方法执行 filters: { formatRichTex ...

  5. openstack考试需要的部署操作

    openstack操作大全 一,keystone 用户 1.创建用户 openstack user create --password 密码 --email邮箱 --domain 域名 用户名字 2. ...

  6. 鸿蒙HarmonyOS实战-ArkTS语言基础类库(并发)

    一.并发 并发是指在一个时间段内,多个事件.任务或操作同时进行或者交替进行的方式.在计算机科学中,特指多个任务或程序同时执行的能力.并发可以提升系统的吞吐量.响应速度和资源利用率,并能更好地处理多用户 ...

  7. .NET8 Hello World!

    ​ 使用ASP.NET Core Web Application模板创建的Empty项目如下: ​ 这是一个最简单的Web项目,运行起来会在根路径响应Hello World! 2.1.1 Progra ...

  8. error pulling image configuration: Get https://eastasia.data.mcr.microsoft.com -- net/http: TLS handshake timeout

    error pulling image configuration: Get https://eastasia.data.mcr.microsoft.com/b29889755b1f4e46b6b44 ...

  9. JavaScript中如何终止forEach循环&跳出for(双层)循环?

    在JavaScript中,forEach方法是用于遍历数组的,通常没有直接终止循环的机制.然而,我们可以使用一些技巧来模拟终止forEach循环.以下是几种常见的方法 1.使用return语句:在fo ...

  10. Nuxt3页面开发实战探索

    title: Nuxt3页面开发实战探索 date: 2024/6/19 updated: 2024/6/19 author: cmdragon excerpt: 摘要:这篇文章是关于Nuxt3页面开 ...