在代码进行优化的时候,发现了switch case太长,有的竟然长达30个远远超过一屏这样在代码的可读性来说很差。特别在我们看代码的时候要拉下拉框我个人觉得这是不合理的。但是我不建议有switch就进行反射或委托来解决。看实际的情况比喻10个以为还是可以接受的。因为switch看起来更加的直接而且效率相对来说是最好的。那下面就用代码来一点点进行解释
1:传统的用法
1.1:现在我们有一个需求通过传递参数来获取相关的信息。首先我们先看方法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public class SwitchMethod { 2 public string GetSerialNumber(string serialNumber) 3 { 4 return serialNumber; 5 } 6 7 public string GetName(string name) 8 { 9 return name; 10 } 11 12 public string GetAge(string age) 13 { 14 return age; 15 } 16 17 public string GetBirthday(string birthday) 18 { 19 return birthday; 20 } 21 22 }
1.2:客户端的调用
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 string action =Console.ReadLine() ; 2 var switchMethod=new SwitchMethod(); 3 switch (action) 4 { 5 case "serialNumber": 6 Console.WriteLine(switchMethod.GetSerialNumber("1234")); 7 break; 8 case "name": 9 Console.WriteLine(switchMethod.GetName("zhangsan")); 10 break; 11 case "age": 12 Console.WriteLine(switchMethod.GetAge("21")); 13 break; 14 case "birthday": 15 Console.WriteLine(switchMethod.GetBirthday("19960201")); 16 break; 17 }
1.3:效果
以上是我们最常规的用法看起来最直观但是你想过没有如果有30个方法呢你还这样进行switch case吗 50,100个呢所以下面我用委托来代码
2:委托替代switch
上面我又发现一个问题action凌乱,如果太多了就搞不清什么是什么了所以我们加入枚举
2.1:建立枚举
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public enum ActionEnum 2 { 3 /// <summary> 4 /// 编号 5 /// </summary> 6 SerialNumber = 0, 7 /// <summary> 8 /// 姓名 9 /// </summary> 10 Name = 1, 11 /// <summary> 12 /// 年龄 13 /// </summary> 14 Age = 2, 15 /// <summary> 16 /// 生日 17 /// </summary> 18 Birthday = 3 19 }
2.2:我采取字典把需要switch的都存起来
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 private static void LoadDictionary() 2 { 3 if (AllDictionary.Count<=0) 4 { 5 var switchMethod = new SwitchMethod(); 6 AllDictionary.Add(ActionEnum.SerialNumber, switchMethod.GetSerialNumber); 7 AllDictionary.Add(ActionEnum.Age, switchMethod.GetAge); 8 AllDictionary.Add(ActionEnum.Birthday, switchMethod.GetBirthday); 9 AllDictionary.Add(ActionEnum.Name, switchMethod.GetName); 10 } 11 }
2.3:建立委托(这是比较简单的其实在方法中还可以提取相似的操作放在委托执行)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public static string Exec(string str,Func<string, string> method) { 2 return method(str); 3 }
2.4:客户端调用
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 Console.WriteLine(Exec("21", AllDictionary[ActionEnum.Age]));
2.5:效果
3:反射替代switch
3.1建立一个自定义Attribute类(目的是为了附带方法中的信息)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public class MethodAttribute : Attribute 2 { 3 public ActionEnum MethodName; 4 5 public MethodAttribute(ActionEnum methodName) 6 { 7 this.MethodName = methodName; 8 } 9 }
3.2:定义一个基类
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public class BaseMethod 2 { 3 public Hashtable GetMethodAttribute<T>(T t) 4 { 5 var hashtable = new Hashtable(); 6 Type type = t.GetType(); 7 foreach (MethodInfo method in type.GetMethods()) 8 { 9 var methodArray = (MethodAttribute[]) method.GetCustomAttributes(typeof (MethodAttribute), false); 10 foreach (MethodAttribute actionMethodAttribute in methodArray) 11 { 12 ActionEnum actionName = actionMethodAttribute.MethodName; 13 hashtable.Add(actionName, method); 14 } 15 } 16 return hashtable; 17 } 18 19 20 public string DoAction(ActionEnum actionName,string str) { 21 Hashtable ht = GetMethodAttribute(this); 22 string message = ht.Contains(actionName) 23 ? ((MethodInfo) ht[actionName]).Invoke(this, new object[] {str}).ToString() 24 : string.Format("{0} 超过范围", actionName); 25 return message; 26 } 27 }
3.3:修改SwitchMethod类并给方法加上特性
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public class SwitchMethod : BaseMethod 2 { 3 [Method(ActionEnum.SerialNumber)] 4 public string GetSerialNumber(string serialNumber) 5 { 6 return serialNumber; 7 } 8 9 [Method(ActionEnum.Name)] 10 public string GetName(string name) 11 { 12 return name; 13 } 14 15 [Method(ActionEnum.Age)] 16 public string GetAge(string age) 17 { 18 return age; 19 } 20 21 [Method(ActionEnum.Birthday)] 22 public string GetBirthday(string birthday) 23 { 24 return birthday; 25 } 26 }
3.4:客户端调用
string result = new SwitchMethod().DoAction(ActionEnum.SerialNumber,"1332");
3.5:注释
3.5.1:type.GetMethods():获取这个类中所有的方法包括基类的方法
3.5.2:method.GetCustomAttributes(typeof (MethodAttribute), false):获取这个方法所有关于MethodAttribute类型的自定义特性
3.5.3:MethodInfo:表示对类中方法的访问
3.6:运行效果
三种方式总结
1:传统的用法
优点:简单易读,效率高
缺点:当量很多的时候会造成方法很长,不易维护,可能修改其中某一个case会引起未知的错误
2:委托
优点:使用委托将公有的进行提取,减少代码量
缺点:加入字典后每次添加都需要在字典后手动添加一个子项。总是觉得别扭,效率稍微差点
3:反射
优点:代码量减少,不在考虑内部如何实现,而且符合开闭原则,只需要添加新的方法,其他地方不作修改。维护性强
缺点:很明显这个效率最差(此处并未加入缓存)
第三种方式参考:http://www.cnblogs.com/vipsoft/archive/2012/10/19/2731126.html