在開發 asp.net 專案中,通常使用一般處理程式(ashx)處理前端傳送過來的請求,因為一個handler會處理多個請求,故ajax請求中一般都會加一個action的引數,在handler里根據這個action做相應的處理或返回相應的資料,這裡大多數人都會想到用switch...case做判斷,一開始我也是用的switch,但漸漸地發現,每個case不像一個程式碼塊,不能為其中的變數提供一個獨立的作用域!而且,如果case的情況比較多的話,程式碼看上去也比較臃腫難維護;
那如何替換掉switch...case呢,我想到了如下兩個方案:
1、用委託字典代替switch...case;
首先在handler裡宣告一個私有的靜態委託字典,key為action字串,value為Func
完整示例程式碼:
namespace WebApplication1
{
public class Handler1 : IHttpHandler
{
static Dictionary<string, Action<HttpContext>> MapActions = new Dictionary<string, Action<HttpContext>>(StringComparer.OrdinalIgnoreCase)
{
{"Add", Add},
{"Sub", Sub}
};
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
try
{
var action = context.Request["Action"];
if (string.IsNullOrEmpty(action))
{
context.Response.StatusCode = (int) HttpStatusCode.BadRequest;
}
if (MapActions.ContainsKey(action))
{
var actionFun = MapActions[action];
if (actionFun != null)
{
actionFun(context);
//或
//actionFun.Invoke(context);
}
else
{
context.Response.StatusCode = (int) HttpStatusCode.NotImplemented;
}
}
else
{
context.Response.StatusCode = (int) HttpStatusCode.NotFound;
}
}
catch (Exception e)
{
context.Response.StatusCode = (int) HttpStatusCode.InternalServerError;
}
finally
{
context.Response.End();
}
}
public static void Add(HttpContext context)
{
int num1 = int.Parse(context.Request["Num1"]);
int num2 = int.Parse(context.Request["Num2"]);
int result = num1 + num2;
context.Response.Write(result);
}
public static void Sub(HttpContext context)
{
int num1 = int.Parse(context.Request["Num1"]);
int num2 = int.Parse(context.Request["Num2"]);
int result = num1 - num2;
context.Response.Write(result);
}
public bool IsReusable
{
get
{
return false;
}
}
}
}
2、利用反射替代switch...case;
利用反射,將action的值與具體的方法對應上;
完整示例程式碼:
namespace WebApplication1
{
public class Handler2 : IHttpHandler
{
static readonly Type[] SearchParamType = new[] { typeof(HttpContext) };
public void ProcessRequest(HttpContext context)
{
var result = ActionInvoke(context);
context.Response.ContentType = "text/plain";
context.Response.Write(result);
}
private object ActionInvoke(HttpContext ctx)
{
var actionFun = this.GetType().GetMethod("ProcessAction_" + ctx.Request["action"] ?? "",
BindingFlags.NonPublic |
BindingFlags.IgnoreCase |
BindingFlags.Instance |
BindingFlags.Public,
null,
SearchParamType,
null);
if (null == actionFun)
{
return "UnknowAction";
}
return actionFun.Invoke(this, new[] { ctx });
}
public int ProcessAction_Add(HttpContext context)
{
int num1 = int.Parse(context.Request["Num1"]);
int num2 = int.Parse(context.Request["Num2"]);
int result = num1 + num2;
return result;
}
public int ProcessAction_Sub(HttpContext context)
{
int num1 = int.Parse(context.Request["Num1"]);
int num2 = int.Parse(context.Request["Num2"]);
int result = num1 - num2;
return result;
}
public bool IsReusable
{
get
{
return false;
}
}
}
}
3、比較兩種方案
反射會造成一定的效能損耗;所以使用委託字典方案更加靠譜;
4、其他方案
可以使用設計模式實現,比如工廠模式,狀態模式,中介模式等,但用在上述這個場景,那麼就有殺雞用牛刀的 感覺了;
5、說明
在簡單的邏輯中,case分支少,很少擴充套件,那麼應該用switch語句,因為簡單明瞭,易於閱讀。
如果在複雜的邏輯中,複雜而且混亂的case,而且經常擴充套件什麼的,就應該用委託和反射,使用快取機制。
6、參考
重構:switch語句改成策略模式還是狀態模式:https://blog.csdn.net/qq_21381465/article/details/51298808
中介模式: https://www.cnblogs.com/insus/p/4134383.html