这是 IOC 的典型用例吗? [英] Is this a typical use case for IOC?

查看:22
本文介绍了这是 IOC 的典型用例吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

My current application allows users to define custom web forms through a set of admin screens. it's essentially an EAV type application. As such, I can't hard code HTML or ASP.NET markup to render a given page. Instead, the UI requests an instance of a Form object from the service layer, which in turn constructs one using a several RDMBS tables. Form contains the kind of classes you would expect to see in such a context: 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 页面中.

Everything works splendidly (for a while). The UI is none the wiser about what sections/fields exist in a given form: It happily renders the Form object it receives into a functional ASP.NET page.

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

A few weeks later, I get a new requirement from the business: When viewing a non-editable (i.e. read-only) versions of a form, certain field values should be merged together and other contrived/calculated fields should are added. No problem I say. Simply amend my service class so that its methods are more explicit:

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 仍然不知道表单中的内容,并且实现了我们的关注点分离.然而,仅仅几周后,该企业提出了一项新要求:在某些情况下,我们应该只应用我上面提到的一些表单转换.

Again everything works great and balance has been restored to the force. The UI continues to be agnostic as to what is in the Form, and our separation of concerns is achieved. Only a few short weeks later, however, the business puts out a new requirement: in certain scenarios, we should apply only some of the form transformations I referenced above.

此时,感觉显式方法"的方法已经走到了尽头,除非我想以方法(OpenFormViewingScenario1、OpenFormViewingScenario2等)爆炸式结束.相反,我引入了另一个间接级别:

At this point, it feels like the "explicit method" approach has reached a dead end, unless I want to end up with an explosion of methods (OpenFormViewingScenario1, OpenFormViewingScenario2, etc). Instead, I introduce another level of indirection:

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 的知识并创建一个实例.

On the surface, this seems like acceptable approach and yet there is a certain smell. Namely, the UI, which had been living in ignorant bliss about the implementation details of OpenFormForViewing, must possess knowledge of and create an instance of IFormViewCreator.

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

推荐答案

据我所知,您需要在将表单发送到 UI 层之前对其进行修改.在我看来,Decorator 应该就位.保留没有 IFormViewCreator 的旧 IFormService 接口.

As I understand the question, you need to modify the Form before sending it off to the UI layer. That sounds to me like a Decorator would be in place. Keep the old IFormService interface without the IFormViewCreator.

您现在可以创建一个或多个实现所需过滤或修改的装饰 FormService.

You can now create one or more Decorating FormService(s) that implement the desired filtering or modification.

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 实现.

You can now decorate your original IFormService implementation with one or more of such Decorators.

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

您可以根据需要将任意数量的装饰器(每个都有自己的责任)包裹在彼此周围.

You can wrap as many Decorators (each with their own responsibility) around each other as you'd like.

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

There's no explicit need for a DI Container to do this, but it fits nicely with other DI patterns. I use Decorator all the time :)

这篇关于这是 IOC 的典型用例吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆