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

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

问题描述

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



这是服务层的外观:

  public class MyFormService:IFormService {

public Form OpenForm(int formId){
//构造并返回具体实现表单
}
}

一切都很出色(一段时间)。 UI对于给定形式中的哪些部分/字段存在是没有用的:它很高兴地将其接收到的Form对象呈现到功能ASP.NET页面中。几周后,我收到了业务的新要求:当查看不可编辑(即只读)版本的表单时,某些字段值应该应该合并,并添加其他设计/计算字段。没问题我说只需修改我的服务类,使其方法更加明确:

  public class MyFormService:IFormService {

public Form OpenFormForEditing(int formId){
//构造并返回Form
的具体实现

public Form OpenFormForViewing(int formId){
//构造和Form
的具体实现//应用额外的转换形式
}
}

再次,一切都很好,平衡已经恢复了力量。用户界面对于表单中的内容仍然是不可知的,我们分离了关注点。然而,短短几个星期之后,业务提出了一个新的要求:在某些情况下,我们应该只应用上面引用的转换形式的



在这一点上,感觉像显式方法方法已经到了一个死胡同,除非我想要结束一些方法(OpenFormViewingScenario1,OpenFormViewingScenario2等)。相反,我引入了另一个间接的层次:

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

public class MyFormService:IFormService {

public Form OpenFormForEditing(int formId){
//构造并返回Form $的具体实现b $ b}

public Form OpenFormForViewing(int formId,IFormViewCreator formViewCreator){
//构造Form
的具体实现//将转换应用于动态字段列表
return formViewCreator.CreateView(form);
}
}

从表面上看,这似乎是可以接受的方法有一定的气味。也就是说,对于OpenFormForViewing的实现细节,对于无知的幸福感,UI必须拥有和创建IFormViewCreator的实例。


  1. 我的问题有两方面:有没有一个
    更好的方式来实现我以后的
    可组合性? (也许是
    使用IoC容器或家庭
    轧制工厂创建
    具体的IFormViewCreator)?

  2. 我从根本上拧了
    abstraction here?


解决方案

根据我的理解,您需要修改表单然后将其发送到UI层。这听起来像是一个装饰器将到位。保留旧的IFormService接口而不需要IFormViewCreator。



现在,您可以创建一个或多个Decorating FormService来实现所需的过滤或修改。

  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)
{
//在这里实现转换/过滤/修改
}
}

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

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

您可以随心所欲地缠绕尽可能多的装饰器(每个都有自己的责任) 。



没有明确的需要DI容器来做到这一点,但它很适合其他DI模式。我一直在使用Decorator:)


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>

Here's what the service layer looks like:

public class MyFormService: IFormService{

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

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
       }
}

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.

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);
       }
}

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. My questions are twofold: Is there a better way to achieve the composability I'm after? (perhaps by using an IoC container or a home rolled factory to create the concrete IFormViewCreator)?
  2. Did I fundamentally screw up the abstraction here?

解决方案

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.

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
    }
}

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.

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天全站免登陆