【问题标题】:Where do I put dependency creation for a Presenter class in a Passive View architecture?在被动视图架构中,我应该在哪里为 Presenter 类创建依赖项?
【发布时间】:2009-05-11 19:14:42
【问题描述】:

我刚刚从演示者类重构了一个新的域类,但我不知道在哪里实例化它。

这是对维护不善的遗留项目进行的更大的持续重构工作的一部分。

Presenter 当前正在由视图的 OnLoad 事件创建,并且视图在构造函数中作为参数传递。 Presenter 中的所有公共方法都是无参数的并且返回 void。它们使用视图的公共属性与视图通信。

视图,本质上是一种简陋的形式,完全取决于演示者。

这是典型的被动视图模式,我想继续坚持下去。这使我陷入困境。我需要为演示者创建一个新域对象的实例以供使用。

  • 如果我通过构造函数传递它,那么视图必须创建它并获得不必要的依赖。
  • 如果我在演示器中的任何位置创建它,我无法在单元测试中将其替换为模拟对象。
  • 如果我将它设为演示者的公共属性,那么我会在使用它的演示者方法上引入创建顺序依赖项,但我仍然没有解决哪个外部类负责创建它。

我目前没有使用任何依赖注入框架。虽然我有兴趣在未来使用它,但源代码仍然很脆弱,无法在其中引入第三方框架。

我愿意接受任何建议。

【问题讨论】:

    标签: c# refactoring dependency-injection mvp


    【解决方案1】:

    我已经做好了!!! 看看这里my repository。我在这里的选择是使用构造函数...满足最贪婪的我确定演示者已启动。在您的情况下,您可以从视图中提供依赖项的特定 impl。

    玩得开心:)

    【讨论】:

    • 你的设计很有趣。您的视图符合被动视图模式,但我从未见过同时使用演示者和控制器完成它。我见过的示例让演示者完成繁重的工作并与域对象和数据存储进行对话。而你的有一个演示者作为中间人,而控制器则在做这项工作。额外层有什么好处?
    • 好处是显而易见的......所有繁重的工作都完成了演示者控制器的职责是管理复杂场景中的导航。这里实现了解耦导航,例如视图不了解其他向导的向导......一切都由控制器处理。
    【解决方案2】:

    我找到了一个更简单的解决方案。这是我原来的课程的一个例子:

    public Presenter(IView view)
    {
        this.View = view;
    }
    

    我想将我的新依赖项作为构造函数参数传递,但也不想将此依赖项添加到我的视图中。构造函数链来救援!

    public Presenter(IView view):this(view, new Dependency()){}
    
    public Presenter(IView view, IDependency dependency)
    {
        this.View = view;
        this.Dependency = dependency;
    }
    

    现在生产代码继续使用原始接口,而单元测试使用新的接口,为视图和依赖项传入模拟。如果依赖项的数量继续增长,则需要进行一些重构,但在不久的将来,这是一个理想的解决方案。

    【讨论】:

      【解决方案3】:

      我现在会选择存储库或工厂。它可以立即进行测试。将来,您可以将其实现替换为 DI 库。

      public class DomainObjectsRepository
      {
          /// <summary>
          /// can not be instantiated, use <see cref="Instance"/> instead.
          /// </summary>
          protected DomainObjectsRepository()
          {
      
          }
      
          static DomainObjectsRepository()
          {
              Instance = new DomainObjectsRepository();
          }
      
          public static DomainObjectsRepository Instance { get; set; }
      
      
          public virtual ICustomerDao GetCustomerDao()
          {
              return new CustomerDao();
          }
      }
      
      public class DomainObjectsRepositoryMock : DomainObjectsRepository
      {
          public override ICustomerDao GetCustomerDao()
          {
              return new CustomerDaoMock();
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-03-19
        • 2018-11-19
        • 1970-01-01
        • 2011-05-07
        • 2017-02-02
        相关资源
        最近更新 更多