When the code was optimized, the switch case was found to be too long, and some 30 more than a screen would be a poor readability of the code. Especially when we look at the code to pull down the box I personally feel that this is unreasonable. However, I do not recommend that a switch be reflected or delegated to resolve. Look at the actual situation analogy 10 thought is still acceptable. Because the switch looks more direct and the efficiency is relatively best. Let's use code to explain it a little bit.
1: The traditional usage
1.1: Now we have a need to pass parameters to get the relevant information. First, we'll look at the method.
public class Switchmethod {
public string Getserialnumber (string serialnumber)
{
return serialnumber;
}
public string GetName (string name)
{
return name;
}
public string Getage (string age)
{
return age;
}
public string Getbirthday (string birthday)
{
return birthday;
}
}
1.2: Calls from the client
String action =console.readline ();
var switchmethod=new switchmethod ();
Switch (action)
{
Case "SerialNumber":
Console.WriteLine (Switchmethod.getserialnumber ("1234"));
Break
Case "Name":
Console.WriteLine (Switchmethod.getname ("Zhangsan"));
Break
Case "Age":
Console.WriteLine (Switchmethod.getage ("21"));
Break
Case "Birthday":
Console.WriteLine (Switchmethod.getbirthday ("19960201"));
Break
}
1.3: Effect
The above is our most conventional usage looks the most intuitive but did you ever think about it if there are 30 ways do you still do the switch case? So I'm going to use the delegate code here.
2: Delegate override switch
I found a problem on the top. Action messy, if too much can not understand what is what is so we add enumeration
2.1: Establishing an enumeration
public enum Actionenum
{
<summary>
Number
</summary>
serialnumber = 0,
<summary>
Name
</summary>
Name = 1,
<summary>
Age
</summary>
Age = 2,
<summary>
Birthday
</summary>
Birthday = 3
}
2.2: I take the dictionary to save all the switch
private static void Loaddictionary ()
{
if (alldictionary.count<=0)
{
var switchmethod = new Switchmethod ();
Alldictionary.add (Actionenum.serialnumber, Switchmethod.getserialnumber);
Alldictionary.add (Actionenum.age, switchmethod.getage);
Alldictionary.add (Actionenum.birthday, switchmethod.getbirthday);
Alldictionary.add (Actionenum.name, switchmethod.getname);
}
}
2.3: Establish a delegate (this is relatively simple in fact, in the method can also extract similar operations placed in the delegate execution)
public static string Exec (String str,func<string, string> method) {
return method (str);
}
2.4: Client Invocation
Console.WriteLine (Exec ("Alldictionary[actionenum.age"));
2.5: Effect
3: Reflection replaces switch
3.1 Create a custom attribute class (for the purpose of attaching the information in the method)
public class Methodattribute:attribute
{
Public Actionenum methodname;
Public Methodattribute (Actionenum methodname)
{
This. methodname = methodname;
}
}
3.2: Define a base class
public class Basemethod
{
Public Hashtable getmethodattribute<t> (t)
{
var hashtable = new Hashtable ();
Type type = T.gettype ();
foreach (MethodInfo method in type.) GetMethods ())
{
var Methodarray = (methodattribute[]) method. GetCustomAttributes (typeof (Methodattribute), false);
foreach (Methodattribute actionmethodattribute in Methodarray)
{
Actionenum actionname = actionmethodattribute.methodname;
Hashtable. Add (ActionName, method);
}
}
return Hashtable;
}
public string doaction (Actionenum actionname,string str) {
Hashtable HT = Getmethodattribute (this);
String message = Ht. Contains (ActionName)
? ((MethodInfo) ht[actionname]). Invoke (this, new object[] {str}). ToString ()
: String. Format ("{0} over range", actionname);
return message;
}
}
3.3: Modify the Switchmethod class and add attributes to the method
public class Switchmethod:basemethod
{
[Method (Actionenum.serialnumber)]
public string Getserialnumber (string serialnumber)
{
return serialnumber;
}
[Method (Actionenum.name)]
public string GetName (string name)
{
return name;
}
[Method (Actionenum.age)]
public string Getage (string age)
{
return age;
}
[Method (Actionenum.birthday)]
public string Getbirthday (string birthday)
{
return birthday;
}
}
3.4: Client Invocation
string result = new Switchmethod (). Doaction (Actionenum.serialnumber, "1332");
3.5: Notes
3.5.1:type. GetMethods (): Gets all the methods in this class that include the base class
3.5.2:method. GetCustomAttributes (typeof (Methodattribute), false): Gets all custom attributes about Methodattribute type for this method
3.5.3:methodinfo: Represents access to methods in a class
3.6: Operation effect
Three ways of summarizing
1: The traditional usage
Advantages: Simple and easy to read, high efficiency
Disadvantage: Many of the equivalent time will cause a long, difficult to maintain, may modify one of the cases will cause unknown error
2: Commissioned
Advantages: Use the delegate to extract the public, reduce the amount of code
Disadvantage: After adding a dictionary, you need to add a subkey manually after the dictionary. I always feel awkward and I'm a little more efficient.
3: Reflection
Advantages: Less code, not in consideration of how the internal implementation, but also in line with the opening and closing principles, only need to add new methods, other places do not make changes. Strong maintenance
Disadvantage: Obviously this is the least efficient (no caching is included here)
Replace switch with reflection
Call different methods according to the different values passed in
protected void Btn_switchclick (object sender, EventArgs e)
{
string result = "";
Switch (ddlmethod.selectedvalue)
{
Case "A":
result = Switchtest.geta ();
Break
Case "B":
result = Switchtest.getb ();
Break
Case "C":
result = Switchtest.getc ();
Break
Default
result = Ddlmethod.selectedvalue + "method not found";
Break
}
Ltrresult.text = result;
}
The following is implemented using the reflection mechanism, which requires a custom attribute class
public class Actionmethodattribute:attribute
{
public string Actiontypename;
Public Actionmethodattribute (String typeName)
{
This. Actiontypename = TypeName;
}
}
Then define a base class
Public abstract class GENERICBLL
{
Public Hashtable getmethodattribute<t> (t)
{
Hashtable ht = new Hashtable ();
Hashtable obj = Cachehandlerif (obj = null)
{
Type type = T.gettype ();
foreach (MethodInfo mi in type. GetMethods ())
{
actionmethodattribute[] mis = (actionmethodattribute[]) mi. GetCustomAttributes (typeof (Actionmethodattribute), false);
foreach (Actionmethodattribute actionmethodattribute in MIS)
{
string actionname = Actionmethodattribute.actiontypename;
Ht. Add (ActionName, MI);
}
}
Cachehandler}
Else
{
HT = (Hashtable) obj;
}
return HT;
}
<summary>
return message;
</summary>
<param name= "ActionName" ></param>
<returns></returns>
public string Doaction (string actionname)
{
String message;
Hashtable HT = Getmethodattribute (this);
if (HT. Contains (ActionName))
{
Message = ((MethodInfo) ht[actionname]). Invoke (this, new object[] {}). ToString ();
}
Else
{
Message = string. Format ("{0} not defined.!", actionname);
throw new Exception (errmsg);
}
return message;
}
}
Implement class inheritance,
public class REFLECTTEST:GENERICBLL
{
[Actionmethod ("A")]
public string Geta ()
{
Return "a called";
}
[Actionmethod ("B")]
public string Getb ()
{
Return "called B";
}
[Actionmethod ("C")]
public string getc ()
{
Return "C called";
}
}
The specific call
protected void Btn_reflectclick (object sender, EventArgs e)
{
string result = Reflecttest.doaction (Ddlmethod.selectedvalue);
Ltrresult.text = result;
}
The code in ASPX is as follows
Select D will prompt no D method
<asp:dropdownlist id= "Ddlmethod" runat= "Server" >
<asp:listitem text= "A" value= "a" >
</asp:ListItem>
<asp:listitem text= "B" value= "B" >
</asp:ListItem>
<asp:listitem text= "C" value= "C" >
</asp:ListItem>
<asp:listitem text= "D" value= "D" >
</asp:ListItem>
</asp:DropDownList>
<br/>
<asp:button id= "Btninvoke" text= "Switch" onclick= "Btn_switchclick" runat= "Server"/>
<asp:button id= "Btninvoker" text= "reflect" onclick= "Btn_reflectclick" runat= "Server"/>
<br>
<asp:literal id= "Ltrresult" runat= "Server"/>