这是 IOC 的典型用例吗?

2024-04-14

我当前的应用程序允许用户通过一组管理屏幕定义自定义 Web 表单。它本质上是一个 EAV 类型的应用程序。因此,我无法对 HTML 或 ASP.NET 标记进行硬编码来呈现给定页面。相反,UI 从服务层请求 Form 对象的实例,服务层又使用多个 RDMBS 表构造一个实例。 Form 包含您希望在这种上下文中看到的类:Form=> IEnumerable<FormSections>=>IEnumerable<FormFields>

服务层如下所示:

public class MyFormService: IFormService{

       public Form OpenForm(int formId){
          //construct and return a concrete implementation of Form 
       }
}

一切都运行良好(暂时)。 UI 并不知道给定表单中存在哪些部分/字段:它很乐意将收到的 Form 对象呈现到功能性 ASP.NET 页面中。

几周后,我收到业务的新要求:当查看表单的不可编辑(即只读)版本时,某些字段值应合并在一起,并应添加其他人为/计算的字段。我说没问题。只需修改我的服务类,使其方法更加明确:

public class MyFormService: IFormService{

       public Form  OpenFormForEditing(int formId){
          //construct and return a concrete implementation of Form 
       }

       public Form  OpenFormForViewing(int formId){
          //construct and a concrete implementation of Form  
          //apply additional transformations to the form
       }
}

再次,一切都运转良好,力量也恢复了平衡。 UI 仍然不知道表单中的内容,并且我们实现了关注点分离。然而仅仅几周后,业务就提出了新的要求:在某些场景下,我们只需要申请some我上面提到的形式转换。

此时,感觉“显式方法”方法已经走进了死胡同,除非我想以方法爆炸结束(OpenFormViewingScenario1、OpenFormViewingScenario2 等)。相反,我引入了另一个间接级别:

public interface IFormViewCreator{
        void CreateView(Form form);
}

public class MyFormService: IFormService{

       public Form  OpenFormForEditing(int formId){
          //construct and return a concrete implementation of Form 
       }

       public Form  OpenFormForViewing(int formId, IFormViewCreator formViewCreator){
          //construct a concrete implementation of Form  
          //apply transformations to the dynamic field list
           return formViewCreator.CreateView(form);
       }
}

从表面上看,这似乎是可以接受的方法,但也有一定的味道。也就是说,一直对 OpenFormForViewing 的实现细节一无所知的 UI 必须具备 IFormViewCreator 的知识并创建 IFormViewCreator 的实例。

  1. 我的问题有两个:是否有 更好的方法来实现 我追求的可组合性? (也许通过 使用 IoC 容器或 home 轧制工厂来创建 具体的 IFormViewCreator)?
  2. 我是否从根本上搞砸了 这里抽象?

据我了解这个问题,您需要先修改表单,然后再将其发送到 UI 层。这对我来说听起来像是装饰者 http://en.wikipedia.org/wiki/Decorator_pattern将会就位。保留旧的 IFormService 接口,不使用 IFormViewCreator。

您现在可以创建一个或多个装饰表单服务来实现所需的过滤或修改。

public class MyDecoratingFormService : IFormService
{
    private readonly IFormService formService;

    public MyDecoratingFormService(IFormService formService)
    {
        if(formService == null)
        {
            throw new ArgumentNullException("formService");
        }

        this.formService = formService;
    }

    public Form OpenFormForEditing(int formId)
    {
        var form = this.formService.OpenFormForEditing(formId);
        return this.TransformForm(form);
    }   

    public Form OpenFormForViewing(int formId)
    {
        var form = this.formService.OpenFormForViewing(formId);
        return this.TransformForm(form);
    }

    public Form TransformForm(Form form)
    {
        // Implement transformation/filtering/modification here
    }
}

现在,您可以使用一个或多个此类装饰器来装饰原始 IFormService 实现。

IFormService formService = new MyDecoratingFormService(new MyFormService());

您可以根据需要将任意多个装饰器(每个装饰器都有自己的责任)相互包裹起来。

没有明确需要 DI 容器来执行此操作,但它非常适合其他 DI 模式。我一直使用装饰器:)

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

这是 IOC 的典型用例吗? 的相关文章

随机推荐

  • 建模单个子表/多个父表

    我正在努力对共享单个表 子表 的多个表 父表 之间的关系进行建模 给定以下父表1 其他父表2 3等类似 Entity Table name parent1 public class ParentEntity1 Id Column name
  • 如何装饰可调用类的实例?

    def decorator fn def wrapper args kwargs print With sour cream and chives return fn args kwargs return wrapper class Pot
  • 为什么 Nokogiri 没有安装?

    我在安装 Nokogiri 时遇到问题 当我跑步时bundle install or gem install nokogiri安装失败 我收到的错误是 注 此失败是由于使用nokogiri org上的安装命令造成的 Building nat
  • 如何结束谈话?

    我已经使用 Bot Framework 创建了一个机器人 并且正在使用conversationID用我的后端对话引擎维护状态 我在文档中找不到用于结束对话的信息 至关重要的是 在某些时候 用户能够发出对话 结束或退出 的信号 以便下次他们开
  • 如何跨域使用 SignalR

    我正在尝试将 SignalR 与跨域一起使用 但在调用启动函数时收到错误消息 错误信息是 Uncaught TypeError Cannot call method start of undefined 我正在使用代码 服务器端 assem
  • 已编译的Azure功能监控:“没有可用数据”

    我在 Azure 上使用几个编译的 C 函数 它们按预期工作 但是当我单击任一功能上的 监视 时 它只显示 无可用数据 我可以在 开发 选项卡的日志上看到该函数正在运行 但希望了解该函数的用法的概述 我有什么遗漏的吗 我也看到这些了我将一个
  • jQuery 上一个按钮在单击时返回到 Q。) 1 而不是一一向后退

    jQuery 上一个按钮无法按预期工作 基本上最好的解释方法是 如果我在回答问题 5 时单击上一个按钮 则它默认为问题 1 而不是问题 4 所以它默认为问题1 这是一个问题 该怎么办 jQuery 位于脚本标签的底部 if i Questi
  • 如何为 docker 容器的日志着色

    我有一个容器 有时在日志中写入对我来说很重要的关键字 我想在终端中以颜色突出显示该单词 但同样重要的是仍然实时查看所有内容日志 follow 我刚刚尝试过命令 docker logs f my app tail 100 grep color
  • 大于100,000的随机数

    我正在用 C C 编写 我想创建很多大于 100 000 的随机数 我该怎么做呢 和rand 你不会那样做rand 但使用较新的 C 附带的适当随机数生成器 请参见例如cppreference com http en cppreferenc
  • Eclipse android ADT安装问题

    我按照每个步骤使用 Eclipse IDE 安装 android ADT 插件 我在 Windows 7 计算机上安装了 Eclipse for Java 我遵循每一步 尽管做了所有的事情 我还是收到以下错误 没有人犯过这个错误 我很着急请
  • Cython:类似 CPP 字典的地图性能

    我一直在比较使用模仿 python 字典的 c 映射与在 cython 中使用普通 python 字典的性能 我在 sklearn 中编写了 fast dict 实现的 简化 变体 https github com scikit learn
  • 如何在linux中的hdfs超级组中添加用户? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我正在研究 hdfs 然后我发现某些内容没有为超级用户执行权限检查 如果我的 linux 用户是 sandy 并且我想将 sandy 添加
  • 如何让tinymce(浏览器内的“富编辑器”)保留缩进

    问题 我将 Drupal 与丰富的编辑器一起使用 而丰富的编辑器喜欢通过删除缩进和格式来破坏我的文本 这在桌面编辑器中是不可接受的 但人们似乎可以在浏览器内编辑器中容忍这种情况 问 如何关闭此功能 我已经四处搜索 但尚未找到告诉富编辑器保留
  • 如何将 Javascript 数组传递给 Spring 控制器类

    我创建了 JS 数组并尝试将数组传递给 Controller 类 但它显示了NullPointerException 我通过 FireBug 检查了 URL 其中值正在传递 但在控制器类中 如果我尝试检索它 则显示 NULL JavaScr
  • List 或 IList [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 谁能向我解释为什么我想在 C 中使用 IList 而不是 List 相关问题 为什么暴露被认为是不好的List
  • Ruby 最大整数

    我需要能够确定 Ruby 中的系统最大整数 有人知道怎么做吗 或者是否可能 FIXNUM MAX 2 0 size 8 2 1 FIXNUM MIN 2 0 size 8 2
  • 自动更新 .net 应用程序

    到目前为止 我已经在 net 中编写了 2 个相当大型的应用程序 它们都需要一个更新工具 以便在我推出新代码时自动更新应用程序 我发现 企业应用程序块更新程序 对于我的需求来说有点过于复杂 并且在发布时我发现 单击一次 令人沮丧 我发现的最
  • 错误:unpack_from 需要缓冲区

    我正在使用 struct 来格式化固定分隔的 txt 文件 这是前两行 Sat Jan 3 18 15 05 2009 62e907b15cbf27d5425399ebf6f0fb50ebb88f18 4a5e1e4baab89f3a325
  • 如何将图像路径和名称上传到数据库 - Codeigniter

    我知道这个问题已经被问过好几次了 但是我发现的所有其他问题都与我想要的不同 我想将文件名和文件路径上传到名为 工厂图像 的表 这样做的最佳方法是什么 我的控制器功能 function do upload config upload path
  • 这是 IOC 的典型用例吗?

    我当前的应用程序允许用户通过一组管理屏幕定义自定义 Web 表单 它本质上是一个 EAV 类型的应用程序 因此 我无法对 HTML 或 ASP NET 标记进行硬编码来呈现给定页面 相反 UI 从服务层请求 Form 对象的实例 服务层又使