翼度科技»论坛 编程开发 .net 查看内容

C# 通过反射(Reflection)调用不同名泛型方法

6

主题

6

帖子

18

积分

新手上路

Rank: 1

积分
18
概述

由于工作需要,需要通过数据类型和方法名控制方法走向
用到的数据类型有8种(string,Int16,Int32,Int64,Boolean,Byte,Single,Double)
读取的方法(参数一致,但是数据不同的泛型方法,返回值也是泛型)暂时只有11种,但肯定的是,后续一定会增加
原本计划排列组合,写个88行代码,但是总觉得重复代码过多,且后续维护极其繁琐
例如:新增一个读取方法,需要额外新增8行数据类型选择代码,繁琐暂且不说,主要是容易出现纰漏
网络上一翻搜寻,找到了反射,完美解决了我的问题,现在想把这个反射分享给大家:
排列组合

没错,我最开始就是排列组合
  1. int datatype = default(int) ; // 决定值类型
  2. int GetType = default(int) ; // 决定通过什么方法读取
  3. //类型选择
  4. switch (datatype)
  5. {
  6.     case 2: res[0] += "'" + Convert.ToString(ReadString(dataaddress , datalen , gettype)) + "',"; break;
  7.     case 4: res[0] += Convert.ToString(ReadInt(dataaddress , datalen , gettype)) + ","; break;
  8.     case 6: res[0] += "'" + Convert.ToString(ReadString(dataaddress , datalen , gettype)) + "',"; break;
  9.     case 7: res[0] += Convert.ToString(ReadUshort(dataaddress , datalen , gettype)) + ","; break;
  10.     case 8: res[0] += Convert.ToString(ReadUint(dataaddress , datalen , gettype)) + ","; break;
  11.     case 9: res[0] += Convert.ToString(ReadULong(dataaddress , datalen , gettype)) + ","; break;
  12.     case 10: res[0] += Convert.ToString(ReadInt(dataaddress , datalen , gettype)) + ","; break;
  13.     case 11: res[0] += Convert.ToString(ReadShort(dataaddress , datalen , gettype)) + ","; break;
  14.     case 12: res[0] += Convert.ToString(ReadByte(dataaddress , datalen , gettype)) + ","; break;
  15.     case 13: res[0] += Convert.ToString(ReadFloat(dataaddress , datalen , gettype)) + ","; break;
  16.     case 14: res[0] += Convert.ToString(ReadDouble(dataaddress , datalen , gettype)) + ","; break;
  17.     case 15: res[0] += Convert.ToString(ReadDouble(dataaddress , datalen , gettype)) + ","; break;
  18.     case 20: res[0] += Convert.ToString(ReadBool(dataaddress , datalen , gettype)).ToLower() + ","; break;
  19.     case 31: res[0] += Convert.ToString(ReadLong(dataaddress , datalen , gettype)) + ","; break;
  20.     default: res[0] += Convert.ToString(ReadUshort(dataaddress , datalen , gettype)) + ","; break;
  21. }
  22. //方法选择
  23. //string
  24. public string ReadString(string StartAddress , int Length , int GetType)
  25. {
  26.     switch (GetType)
  27.     {
  28.         case 1: return ModbusTcpRead<string>(StartAddress , Length);
  29.         case 2: return ModbusRtuRead<string>(StartAddress , Length);
  30.         case 3: return ModbusRtuOverTcpRead<string>(StartAddress , Length);
  31.         case 5: return InovanceTcpNetRead<string>(StartAddress , Length);
  32.         case 6: return KeyenceMcNetRead<string>(StartAddress , Length);
  33.         case 7: return MelsecMcNetRead<string>(StartAddress , Length);
  34.         case 8: return OmronFinsNetRead<string>(StartAddress , Length);
  35.         case 9: return PanasonicMcNetRead<string>(StartAddress , Length);
  36.         case 10: return SiemensS7NetRead<string>(StartAddress , Length);
  37.         case 11: return MelsecFxSerialOverTcpRead<string>(StartAddress , Length);
  38.         case 12: return KeyenceMcAsciiNetRead<string>(StartAddress , Length);
  39.         default: return ModbusTcpRead<string>(StartAddress , Length);
  40.     }
  41. }
  42. //Bool
  43. public bool ReadBool(string StartAddress , int Length , int GetType)
  44. {
  45.     switch (GetType)
  46.     {
  47.         case 1: return ModbusTcpRead<bool>(StartAddress , Length);
  48.         case 2: return ModbusRtuRead<bool>(StartAddress , Length);
  49.         case 3: return ModbusRtuOverTcpRead<bool>(StartAddress , Length);
  50.         case 5: return InovanceTcpNetRead<bool>(StartAddress , Length);
  51.         case 6: return KeyenceMcNetRead<bool>(StartAddress , Length);
  52.         case 7: return MelsecMcNetRead<bool>(StartAddress , Length);
  53.         case 8: return OmronFinsNetRead<bool>(StartAddress , Length);
  54.         case 9: return PanasonicMcNetRead<bool>(StartAddress , Length);
  55.         case 10: return SiemensS7NetRead<bool>(StartAddress , Length);
  56.         case 11: return MelsecFxSerialOverTcpRead<bool>(StartAddress , Length);
  57.         case 12: return KeyenceMcAsciiNetRead<bool>(StartAddress , Length);
  58.         default: return ModbusTcpRead<bool>(StartAddress , Length);
  59.     }
  60. }
  61. ......(就不全部列出来了,排列组合,懂得吧?)
复制代码
或许你发现了什么异常,感觉我这么写不太对,应该先控制方法,在控制值类型,但,没区别,还是排列组合,只不过分散了而已
以上代码也不难看出,重复代码非常多,几乎就是copy一份,然后改一下泛型传入
所以我在想,能不能吧参数转换成泛型填入,然后显然不行,后来找到了反射这个法宝
反射(正片开始)
  1. int datatype = default(int) ; // 决定值类型
  2. int GetType = default(int) ; // 决定通过什么方法读取
  3. //方法名
  4. string methodName = "ModbusTcpRead";
  5. switch (gettype)
  6. {
  7.     case 1: methodName = "ModbusTcpRead"; break;
  8.     case 2: methodName = "ModbusRtuRead"; break;
  9.     case 3: methodName = "ModbusRtuOverTcpRead"; break;
  10.     case 5: methodName = "InovanceTcpNetRead"; break;
  11.     case 6: methodName = "KeyenceMcNetRead"; break;
  12.     case 7: methodName = "MelsecMcNetRead"; break;
  13.     case 8: methodName = "OmronFinsNetRead"; break;
  14.     case 9: methodName = "PanasonicMcNetRead"; break;
  15.     case 10: methodName = "SiemensS7NetRead"; break;
  16.     case 11: methodName = "MelsecFxSerialOverTcpRead"; break;
  17.     case 12: methodName = "KeyenceMcAsciiNetRead"; break;
  18.     default: methodName = "ModbusTcpRead"; break;
  19. }
  20. //数据值类型
  21. string type = "System.Int32";
  22. switch (datatype)
  23. {
  24.     case 2: type = "System.String"; break;
  25.     case 4: type = "System.Int32"; break;
  26.     case 6: type = "System.String"; break;
  27.     case 7: type = "System.UInt16"; break;
  28.     case 8: type = "System.UInt32"; break;
  29.     case 9: type = "System.UInt64"; break;
  30.     case 10: type = "System.Int32"; break;
  31.     case 11: type = "System.Int16"; break;
  32.     case 12: type = "System.Byte"; break;
  33.     case 13: type = "System.Single"; break;//float
  34.     case 14: type = "System.Double"; break;
  35.     case 15: type = "System.Double"; break;
  36.     case 20: type = "System.Boolean"; break;
  37.     case 31: type = "System.Int64"; break;
  38.     default: type = "System.UInt16"; break;
  39. }
  40. MethodInfo method = typeof(PLCOper).GetMethod(methodName , BindingFlags.Instance | BindingFlags.Public);
  41. MethodInfo genericMethod = method.MakeGenericMethod(Type.GetType(type , false));
  42. object result = genericMethod.Invoke(this , new object[] { dataaddress , datalen });
  43. //这里有几点要提醒
  44. //1、typeof(PLCOper) 括号里的类名必须是调用方法的父类名
  45. //2、GetMethod 第二个参数,前者用于过滤方法的属性,比如是静态还是非静态,我方法全是非静态,所以需要BindingFlags.Instance 参数
  46. //3、Invoke 第一个参数,如果调用静态方法,传入null就好,实例内的方法,需要传入this
  47. //4、Invoke 第二个参数,是方法的入参
复制代码
是不是简洁非常多?(看起来没区别或许是因为排列组合我没全部写出来?)
以后新增方法名也只需要在这里改一次就可以了
非常完美!
结束

感谢看到这里。

来源:https://www.cnblogs.com/HookDing/p/18326960
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具