在开发 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. spring boot 2.x 系列 —— spring boot 整合 dubbo

    文章目录 一. 项目结构说明 二.关键依赖 三.公共模块(boot-dubbo-common) 四. 服务提供者(boot-dubbo-provider) 4.1 提供方配置 4.2 使用注解@Ser ...

  2. vue随笔

    1.vue基础 Vue 是一个mvvm 的渐进式框架.Angular 是一个mvc的.所以vue的重点更偏向于mv 他的使用方式 大家会发现里面带有大量的$的属性. 学习vue的指令 V-for  用 ...

  3. 【朝花夕拾】Android自定义View篇之(五)Android事件分发机制(上)Touch三个重要方法的处理逻辑

    前言 转载请注明,转自[https://www.cnblogs.com/andy-songwei/p/10998855.html]谢谢! 在自定义View中,经常需要处理Android事件分发的问题, ...

  4. 用.NET Core实现一个类似于饿了吗的简易拆红包功能

      需求说明 以前很讨厌点外卖的我,最近中午经常点外卖,因为确实很方便,提前点好餐,算准时间,就可以在下班的时候吃上饭,然后省下的那些时间就可以在中午的时候多休息一下了. 点餐结束后,会有一个好友分享 ...

  5. Input标签中Type的类型及详细用法

    Input表示Form表单中的一种输入对象,其又随Type类型的不同而分文本输入框,密码输入框,单选/复选框,提交/重置按钮等,下面一一介绍.1,type=text输入类型是text,这是我们见的最多 ...

  6. 我在工作中遇到的redis集群使用

    写次随笔,给自己工作学习中记录一个笔记 废话不多说,直接上代码: 功能:将相关信息存到redis中,并设置过期时间,如果redis中有,从redis获取,如果没有,从mysql中获取.redis配置了 ...

  7. ajax 前端发含有列表的数据

    在前端页面也可以给后端发送一个包含列表的数据 html <body> <h3>index页面 </h3> <input type="text&quo ...

  8. 对scanner.close方法的误解以及无法补救的错误

    scanner错误关闭导致的异常 public class test2 { public static void main(String[] args) { Scanner scanner1 = ne ...

  9. python接口自动化(三十)--html测试报告通过邮件发出去——中(详解)

    简介 上一篇,我们虽然已经将生成的最新的测试报告发出去了,但是MIMEText 只能发送正文,无法带附件,因此我还需要继续改造我们的代码,实现可以发送带有附件的邮件.发送带附件的需要导入另外一个模块 ...

  10. 开设“C程序答疑解惑”的初衷

    博主经常在QQ群里.论坛里看到好多C语言初学者,甚至是有一定编程经验的人,咨询在编程中遇到的一些稀奇古怪的问题.博主对这些问题做过分析汇总,有些问题确实隐蔽的非常深,像break关键字用的不对啦,局部 ...