如何在MVC模式中管理多个表单

时间:2013-12-08 13:00:43

标签: c# winforms forms model-view-controller circular-dependency

我正在尝试在我的新项目中使用Model-View-Controller-Pattern,一个Windows Forms C#Application。 我的项目分为几个子项目:

Core
UI (View)
Controller
Model
Services
Helper
Tests

项目依赖如下:Project Dependencies (generated by Visual Studio

我的UI-Project包含2个表单,ListForm和AddForm(还有其他表单,但这些与此问题无关)。

  • 在Controller-Project中,我有不同表单的接口,Controller用它来更新View。

  • 在Core-Project中,我初始化了一个新的ListForm,Controller和Model。

现在,如果用户单击ListForm中的Add-Button,我希望AddForm显示。 但是如果Controller甚至不知道UI-Project,我如何在Controller中创建一个新的AddForm实例呢?

我尝试使用服务,但由于服务必须知道用于创建实例的UI-Project,因此我会有一个循环依赖(根据Visual Studio)。

如果用户单击ListForm中的Add-Button,如何显示AddForm? (一次显示最多1个AddForm)。

1 个答案:

答案 0 :(得分:3)

可能的方法之一涉及控制器工厂。工厂负责创建控制器和视图,并将它们连接在一起。

工厂应该是可配置的,因此您可以针对不同的视图集进行不同的实现 - 用于构建实际ui的一组视图具有其自己的工厂,另一个测试集具有另一个工厂等。所有工厂都通过相同的api,以便您只在必要时重新配置工厂。实现此类工厂的一种可能方法是使用IoC容器,它可以简化实现,但不是必需的。使用IoC容器,您只需注册视图的不同实现,并可以重复使用相同的工厂实现,而没有IoC容器,您需要为每组视图额外实现工厂。

然后,您的父控制器使用工厂创建子控制器的实例。工厂返回子控制器,并在其中注入适当的视图。父控制器调用子控制器上的ShowView,它只是使视图可见,或者子控制器甚至可以在创建时自动显示视图。

编辑:创建控制器/视图的示例工厂:

在控制器层中:

public interface IControllerFactory
{
    TController CreateControllerAndView<TController>()
         where TController : Controller;
}

public class ControllerFactory
{
    // actual provider
    private static IControllerFactory _provider;

    // factory method
    public static TController
        CreateControllerAndView<TController>() where T : Controller
    {
        return _provider.CreateController<TController>();
    }

    public static void SetProvider( IControllerFactory provider )
    {
        _provider = provider;
    }
}

无论何时想要创建新控制器,都可以参考工厂:

var controller = ControllerFactory.CreateControllerAndView<UserController>();

请注意,工厂不依赖任何东西,它只是定义,尚未实现。

然后,在最上层的某个地方,可能在启动项目中,实现了一个具体的提供者:

public class ConcreteControllerFactory : IControllerFactory
{
    public TController CreateControllerAndView<TController>()
    {
        // since you are in the top most layer, you know all types from
        // underlaying layers, including controllers and views

        // IoC would help here a lot! But without it:

        if ( typeof<TController> == typeof<UserController> )
        {
            IUserView view = new UIUserView();
            UserController c = new UserController( view );
        }
        ...
    }
}

然后在某处

ControllerFactory.SetProvider( new ConcreteControllerFactory() );

通过这种方式,您可以将任何特定的提供程序插入工厂,测试提供程序,ui提供程序等等。实际的实施可能会有所不同,但你应该明白这一点。