在开发 asp.net 项目中,通常使用一般处理程序(ashx)处理前端发送过来的请求,因为一个handler会处理多个请求,故ajax请求中一般都会加一个action的参数,在handler里根据这个action做相应的处理或返回相应的数据,这里大多数人都会想到用switch...case做判断,一开始我也是用的switch,但渐渐地发现,每个case不像一个代码块,不能为其中的变量提供一个独立的作用域!而且,如果case的情况比较多的话,代码看上去也比较臃肿难维护;

那如何替换掉switch...case呢,我想到了如下两个方案:

1、用委托字典代替switch...case;

首先在handler里声明一个私有的静态委托字典,key为action字符串,value为Func委托;然后把action和对应的方法添加到字典中即可;

完整示例代码:

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


asp.net ashx处理程序中switch case的替代方案总结的更多相关文章

  1. Javascript 中 switch case 等于 (== )还是 恒等于(===)?

    Javascript 中 switch case 等于 (== )还是 恒等于(===)? 可以测试一下以下代码,这个 case 中是 等于(==)还是恒等于(===) <script> ...

  2. python中Switch/Case实现

    学习Python过程中,发现没有switch-case,过去写C习惯用Switch/Case语句,官方文档说通过if-elif实现.所以不妨自己来实现Switch/Case功能. 方法一 通过字典实现 ...

  3. Python里如何实现C中switch...case的功能

    python没有switch case 不过可以通过建立字典实现类似的功能 例子:根据输入的年月日,判断是该年中的第几天 y = int(input('请输入年:')) m = int(input(' ...

  4. asp.net 登陆后在ashx处理程序中获取不到Session

    登录后存储Session,另一个页面Ajax请求 ashx页面,发现无法获取到Session,Session is NULL  使用“IReadOnlySessionState”这个接口就可以

  5. js中switch/case分支的值可以是变量或表达式

    在一些高级语言如C#中,switch分支的值只能是常量,而js中可以是变量或表达式: <!DOCTYPE html> <html lang="en"> &l ...

  6. thymeleaf中switch case多出一个空行

    以下是<thymeleaf3.0.5中文参考手册.pdf>中的代码,官方代码没有具体去查询. <div th:switch="${user.role}"> ...

  7. C# 中Switch case 返回不止用break

    Switch(temp) { case "A": //跳出循环 break; case "B": //返回值 return var; case "C& ...

  8. 在ashx处理程序中,如果返回json串数据?

    可以通过一下代码: using System.Collections.Generic;using System.Web.Script.Serialization; SortedDictionary&l ...

  9. 简谈switch case

    工作中从buff里截取了一个字符串,然后和配置文件中的字符串名字对比 ,如果一样,处理,不一样,elseif 再判断,再处理! switch(){case : case :...... }先说语法,再 ...

随机推荐

  1. Storm 学习之路(六)—— Storm项目三种打包方式对比分析

    一.简介 在将Storm Topology提交到服务器集群运行时,需要先将项目进行打包.本文主要对比分析各种打包方式,并将打包过程中需要注意的事项进行说明.主要打包方式有以下三种: 第一种:不加任何插 ...

  2. java基础知识总结(二)

    Java中的代码块 java中的代码块是用{}括起来的代码,进行一些功能的限定 静态代码块:在类第一次被初始化的是后执行,负责一些类的初始化操作,仅仅只执行一次 构造代码块:顾名思义,辅助构造器进行初 ...

  3. Mac安装MySQL-python报错解决

    Mac安装MySQL-pyhton报错 今天在Mac上安装MySQL-python报错,搜遍网络都说什么mysql config路径问题,但是都不行. 解决方案 一开始遇到的问题是: Complete ...

  4. Windows和linux环境下按文件名和字符串搜索命令

    Windows 1.遍历C盘下所有txt 命令:for /r c:\ %i in (*.txt) do @echo %i 注释:for 循环的意思 /r 按照路径搜索 c:\ 路径 %i in   ( ...

  5. Python之Pandas库学习(二):数据读写

    1. I/O API工具 读取函数 写入函数 read_csv to_csv read_excel to_excel read_hdf to_hdf read_sql to_sql read_json ...

  6. win10win7office系列激活工具 KMSAuto Net 2016 v1.5.4 绿色便携版

    下载地址:点我 KMSpico又称KMS激活工具,KMSpico是目前成功且经常更新的Windows激活工具,可以激活任何版本的window系统和任何版本的Office软件,即使是win8和offic ...

  7. java 带静态域的导出类创建时都发生了什么?

    先按从基类到导出类的顺序初始化静态域(之前已经初始化过的静态域不再初始化) 再按从基类到导出类的顺序初始化类,即基类普通字段+基类构造器主体+导出类字段+导出类主体... package test; ...

  8. SpringCloud解析之Eureka

    本文基于Spring Cloud Edgware.SR6版本,从功能和架构上解析Eureka,让大家对Eureka有一个较为清晰的认识(本文默认大家对分布式微服务有一个初步的概念和理解,本文不涉及或少 ...

  9. 关系型数据库MySql简介

    什么是关系型数据库? 数据库就是用来存储数据的仓库,是一种特殊的文件. 根据存储的数据不同,划分为关系型数据库和非关系型数据库. 关系型数据库就是指 建立在关系模型基础上的数据库,通俗来讲这种数据库就 ...

  10. C#使用sqlite-net搭建简易的ORM

    SQLite简易版ORM 首先打开项目,使用nuget搜索sqlite-net,如下图: 下载完成后,我们会多出两个文件,SQLite.cs和SQLiteAsync.cs. 我们新建一个文件夹SQLi ...