可以更换大开关吗?

2024-03-22

我有一个名为“ReportController.aspx”的页面,其目的是根据查询字符串参数实例化报告(类)

        switch (Request.QueryString["Report"])
        {                
            case "ReportA":
                CreateReportAReport("ReportA's Title");
                break;
            case "ReportB":
                CreateReportBReport("ReportB's Title");
                break;                
            case "ReportC":
                CreateReportCReport("ReportC's Title");
                break;
            case "ReportD":
                CreateReportDReport("ReportD's Title");
                break;
                ...

基本上,每次需要新报告时,都会产生添加案例和添加方法的开销。这个 switch 语句可能会变得非常非常长。我读到可以使用字典将报告映射到?。使用字典会是什么样子(假设这是更好的方法)。

Also, CreateReportXReport方法基本上将一堆附加的 QueryString 值传递给报表类的构造函数(每个报表类都有不同的构造函数)。


必须在某处输入新信息,这是不可避免的;关键是将其从代码中删除,以避免因如此微不足道的更改而重新编译和重新部署。

一些不错的选择是在 XML 配置文件中列出这些值,或者更好的是在数据库中列出这些值。

您可能希望用这些数据填写一本字典,无论其来源如何。这会:

  • 使缓存变得容易
  • 打造干净、快速的代码

当需要将数据从配置中提取到代码中时,您可以将项目添加到字典中,如下所示:

Dictionary<string, IReportCreator> = configDataGetter.GetReportDataFromDB().
    ToDictionary(r => r.Name, myReportCreatorFactory(r => r.ReportID))

此示例假设您将数据作为某种实体对象获取,并使用一个工厂,该工厂将使用策略模式 http://en.wikipedia.org/wiki/Strategy_pattern用于创建报告的代码。当然,有无数种方法可以做到这一点。

我认为这些报告过于广泛、多样且性质不同,以至于您不能只将 sql 和样式构建块放入数据库中?

Edit根据op的评论:

啊,明白了。好吧,我不知道你有多少时间,但只要你把一切都投入到某种形式中factory http://en.wikipedia.org/wiki/Factory_method_pattern,您稍后会有更好的选择。我将从我做过的类似事情中给你一些想法,希望对你有所帮助。每个步骤本身都是一个改进,但也是真正将报告逻辑与此 shell 代码分离的一小步。此外,我可以看到你已经知道你在做什么,我确信知道我下面要说的一些内容,但我不知道你知道什么,这对其他人会有帮助。

首先,将代码中的所有信息提取到数据库(如果还没有),然后在改进设置时添加更多数据库字段(以及一两个表)。

您可能已经知道了,但我会向其他人提及它,以查看我上面引用的策略模式。您可以让每个“报告函数”的自定义逻辑实际上位于各种策略类的构造函数中。它们都将从您的基础 ReportGenerator 继承(或使用通用的 IReportGenerator 接口)。他们可以而且应该共享相同的构造函数;不同的报告参数将由字典类型的参数处理。每个类的构造函数实现都会知道需要的变量类型(来自数据库配置),并相应地转换/使用它们。

下一步可能是真正摆脱工厂中的 select 语句,使用反射 http://www.codeproject.com/Articles/17269/Reflection-in-C-Tutorial。您必须将类的名称作为数据库中报告配置数据的一部分(并且具有公共构造函数)。

此时,添加新报告的方法非常干净,即使您每次都必须添加一个新类。那么好。它满足了单一职责 http://en.wikipedia.org/wiki/Single_responsibility_principle and 打开关闭 http://en.wikipedia.org/wiki/Open/closed_principle校长。

现在,只剩下最后一步了从您的应用程序中删除类,因此可以即时添加/编辑它们。查看MEF http://managed%20extensibility%20framework。这就是它的用途。您可能会在互联网上找到一些您可能会发现的东西不应该使用是CodeDom http://msdn.microsoft.com/en-us/library/y2k85ax6.aspx(在没有其他东西的情况下很棒,但 MEF 更好)以及 .NET 5 中的编译即服务功能。MEF 是最佳选择。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

可以更换大开关吗? 的相关文章

随机推荐

  • 使用 WIF 在 .NET Web Farm 中为多个电子商务网站实施 SSO?

    我有一个我认为相当复杂的问题 所以我会尽力在这里阐明它 我正在寻找单点登录 SSO 解决方案 我知道有很多选择 但在我添加了它们需要满足的标准时排除了其中的大多数 以下是标准 1 SSO 必须添加到现有 系统 中 2 现有 系统 由 X 个
  • 谷歌是如何获得地图上邮政编码的轮廓的?

    例如 http g co maps 2dpkj http g co maps 2dpkj有邮政编码区域周围的轮廓 我知道这无法通过 API 获得 但我还可以从哪里获取此数据 例如 KML 格式 这是英国数据 最有可能的Google 与英国地
  • 外部 SQLite 文件内容访问错误

    我有以下代码 它给出了如下运行时错误 为什么 try String myPath DB PATH DB NAME mDB SQLiteDatabase openDatabase myPath null SQLiteDatabase OPEN
  • Push API 和服务器发送事件有什么区别?

    从文档中我可以看出Push API http w3c github io push api and 服务器发送事件 http www html5rocks com en tutorials eventsource basics 两者都是半双
  • 在没有源的情况下更改 .jar 文件?

    我有一个基于 Java 的 TCP 客户端 它与我们的生产服务器通信 我正在重写它 客户端对服务器的 IP 和端口进行硬编码 我想要做的就是将客户端中的 IP 地址更改为 127 0 0 1 我可以在我的开发盒上使用相同的端口号 问题是 我
  • 爪哇。隐式超级构造函数 Employee() 未定义。必须显式调用另一个构造函数[重复]

    这个问题在这里已经有答案了 您好 我是 Java 新手 我在生产工作线程类中遇到此错误 我的生产工作线程构造函数显示显式调用另一个构造函数 我不知道该怎么办 import java util Date public class Employ
  • Python 或 PHP 中的感知哈希算法? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 相同运算符优先级的结合性 -- *start++

    为什么会出现下面的表达式 total start 评估为 total start And not total start though this doesn t really matter either it would be the sa
  • 有 Delphi XE2 样式库吗?

    在 XE2 中 有一个新函数 styles 用于 VCL vsf 和 Firemonkey styles 有些是在C Program Files Embarcadero RAD Studio 9 0 Redist styles目录 创建新样
  • 同步视图模型和视图

    我有一个由一些节点和一些连接器组成的视图模型 public class ViewModel public List
  • 更改滚动时的 URL 哈希并保持后退按钮正常工作

    在具有固定顶部菜单和锚点导航的一页布局上 我有一个 scrollspy 它可以更改滚动时的片段标 识符 根据滚动位置为菜单链接提供一个活动类 并使用 Velocity js 将滚动动画到锚点 不幸的是 它还做了什么 当单击浏览器后退按钮时
  • 在 JavaScript 中递归构建 Promise 链 - 内存注意事项

    In 这个答案 https stackoverflow com a 29906627 3478010 递归地构建承诺链 稍微简化一下 我们有 function foo function doo always return a promise
  • 将箭头放在 3d 图中的向量上

    I plotted the eigenvectors of some 3D data and was wondering if there is currently already a way to put arrowheads on th
  • 存储 ASP.NET 密钥、密码的安全方法

    存储网站密钥和 或密码的最佳实践是什么 这些密钥用于各种第 3 方 Web 服务 最好将它们放在 Web config 文件中 数据库中或以某种方式加密吗 您可以将加密值存储在 config 文件中 ASP NET 2 0 将即时解密它们
  • 如何查看我的 Redis 数据库 current_size?

    我知道 redis cli 以及 info 和 config 命令 但是 他们没有任何说明当前数据库大小的信息 我怎样才能弄清楚这一点 使用INFO命令 完整详细信息在这里 http redis io commands info http
  • VSCode 1.14.0 7月更新有重大问题:如何回滚?

    因此 新的 VSCode 更新版本 1 14 0 会导致以下主要问题 CPU 使用率高 导致冻结 随机崩溃 扩展不可用 IntelliSense 工作一半时间 所以我的问题是如何将 VSCode 回滚到以前的版本而不丢失我的配置 1 14
  • 如何测试放置在子文件夹中的 django 应用程序?

    我在测试分组在子文件夹中的 django 应用程序时遇到问题 好吧 让我解释一下情况 标准 django 项目结构如下所示 django project appname1 appname2 appname3 lib tests docs s
  • 将 NSColor 转换为 RGB

    我正在尝试将 NSColor 转换为 RGB 但它似乎给出了完全错误的结果 NSColor testColor NSColor colorWithCalibratedWhite 0 65 alpha 1 0 const CGFloat co
  • 输入类型提交与输入类型按钮

    我一直在尝试用 PHP 解决一个恼人的行为 我认为 也许你们中的一些人也遇到过同样的情况并有一些想法 我有一个 html 表单 并且使用一个带有 onClick 事件的元素来调用 javascript 函数 处理脚本的内容后 我执行 for
  • 可以更换大开关吗?

    我有一个名为 ReportController aspx 的页面 其目的是根据查询字符串参数实例化报告 类 switch Request QueryString Report case ReportA CreateReportAReport