|
概述
由于工作需要,需要通过数据类型和方法名控制方法走向
用到的数据类型有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 第二个参数,是方法的入参
复制代码 是不是简洁非常多?(看起来没区别或许是因为排列组合我没全部写出来?)
以后新增方法名也只需要在这里改一次就可以了
非常完美!
结束
感谢看到这里。
来源:https://www.cnblogs.com/HookDing/p/18326960
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作! |
|