你的位置:首页 > ASP.net教程

[ASP.net教程]用反射或委托优化switch太长的方法


  在代码进行优化的时候,发现了switch case太长,有的竟然长达30个远远超过一屏这样在代码的可读性来说很差。特别在我们看代码的时候要拉下拉框我个人觉得这是不合理的。但是我不建议有switch就进行反射或委托来解决。看实际的情况比喻10个以为还是可以接受的。因为switch看起来更加的直接而且效率相对来说是最好的。那下面就用代码来一点点进行解释

1:传统的用法

1.1:现在我们有一个需求通过传递参数来获取相关的信息。首先我们先看方法

 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:客户端的调用

 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:建立枚举

 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 = 319   }

action枚举

2.2:我采取字典把需要switch的都存起来

 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:建立委托(这是比较简单的其实在方法中还可以提取相似的操作放在委托执行)

1 public static string Exec(string str,Func<string, string> method) {2       return method(str);3     } 

委托

2.4:客户端调用

1 Console.WriteLine(Exec("21", AllDictionary[ActionEnum.Age]));

客户端调用

2.5:效果

3:反射替代switch

 3.1建立一个自定义Attribute类(目的是为了附带方法中的信息)

1 public class MethodAttribute : Attribute2   {3     public ActionEnum MethodName;4 5     public MethodAttribute(ActionEnum methodName)6     {7       this.MethodName = methodName;8     }9   }

特性类

3.2:定义一个基类

 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类并给方法加上特性

 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   }

SwitchMethod 类

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