如何在MVC模式中实现类之间的通信?

时间:2013-05-10 00:45:23

标签: c# events design-patterns model-view-controller

序言:这个问题与ASP.NET MVC框架无关。

编辑:更清楚的是,应用程序是用C#编写的游戏,因此各种Web框架都不适用。


在使用MVC模式构建内容时,如何最好地将类与事件连接起来?

我想写一些MVC代码,以便我可以更多地了解设计模式。我理解为什么模式的这三个元素中的每一个都应该是分开的,但我不确定如何实现将它们连接在一起。我在C#中写这个,我也是新手,我觉得应该使用事件。我主要不确定如何正确订阅/取消订阅活动,我需要进行健全性检查。

例如,我将发布视图/控制器类。在此示例中,View希望发送DataRequest事件,并且Controller希望订阅该事件以便将其传递给Model。另一方面,Controller会在某个时候引发View应该订阅的DataUpdated事件。我实现他们如何相互订阅的方式是否有意义?

////////////////////////////////////////////////////
public class UIScreenView
{
    public event System.EventHandler<System.EventArgs> DataRequestedEvent;

    //====================================
    private void DataUpdatedEventHandler(object sender, System.EventArgs args);


    //====================================
    //====================================
    public void Subscribe(UIScreenController controller)
    {
        controller.DataUpdatedEvent += DataUpdatedEventHandler;
        controller.Subscribe(this);
    }

    //====================================
    //====================================
    public void UnSubscribe(UIScreenController controller)
    {
        controller.DataUpdatedEvent -= DataUpdatedEventHandler;
        controller.UnSubscribe(this);
    }
}

和控制器:

public class UIScreenController
{
    private UIScreenView view;

    public event System.EventHandler<System.EventArgs> DataUpdatedEvent;

    private void DataRequestedEventHandler(object sender, System.EventArgs args);

    public void Init(UIScreenView v)
    {
        view = v;

        if (view != null)
        {
            view.Subscribe(this);
        }
    }

    ~UIScreenController()
    {
        if (view)
        {
            view.UnSubscribe(this);
            view = null;    
        }
    }

    public void Subscribe(UIScreenView view)
    {
        view.DataRequestedEvent += DataRequestedEventHandler;
    }

    public void UnSubscribe(UIScreenView view)
    {
        view.DataRequestedEvent -= DataRequestedEventHandler;
    }

    private void DataRequestedEventHandler(object sender, System.EventArgs args)
    {
        //request data from model
    }
}

3 个答案:

答案 0 :(得分:2)

首先,您所描述的内容称为Model-View-Presenter。到目前为止,我发现的最好的描述是罗伯特·马丁的“敏捷原则,模式和实践在c#”。

其次,您不需要MVP事件。我们的想法是,演示者和视图相互引用并了解其接口,以便直接调用数据请求/更新。

第三,对于没有经验的开发者来说,这种模式可能很麻烦。好处是视图可以用假视图替换,因此您可以轻松地对演示者进行单元测试。但是,如果这是oop的开始,那么将视图和演示者合并到一个类中的贫血方法可能会更简单。

答案 1 :(得分:2)

你做过和尝试过的是MVP模式,而不是MVC。简而言之,MVC模式用于请求 - 响应架构而不是事件驱动。流程是:

  • UI执行请求
  • 控制器接受请求
  • 控制器处理请求(例如访问模型等)
  • Controller将响应发送给UI

如果你想在C#中实现它,我假设winform,那么你的请求将在事件内处理。让我们在你的游戏中说你选择菜单加载游戏,之后需要显示已保存的游戏数据。

以下示例只是一个例子,因此期望应用非现实生活逻辑。控制器将如下:

public class SaveDataController
{
    public SaveData[] GetSaveData()
    {
        return Model.GetSaveData();
    }
}

用户界面就像:

public void LoadGameButton_Click(object sender, EventArgs e)
{
    SaveDataController controller = new SaveDataController();
    SaveData[] saveData = controller.GetSaveData();
    SaveDataList.DataSource = saveData;
}

此示例显示正在按钮单击事件中启动对控制器的请求。

正如其他人已经说过的那样,MVC架构不适合非Web应用程序(或事件驱动),因为它不处理事件方法。大多数UI逻辑都将在事件中处理。

答案 2 :(得分:1)

你有点倒退了。 MVC的主要教训之一(与WebForms类似)是 Web应用程序中没有任何“事件”。您所拥有的只是HTTP规范,它将客户端和服务器之间的事务定义为GET / POST(不太常见,PUT / DELETE)。在MVC中没有“按钮点击”这样的东西。相反,您有来自页面上的表单的HTTP POST。

此外,每个HTTP请求都与之前的HTTP请求完全断开,并且在客户端和服务器之间保持连接打开并不是一个好方法。所有服务器实际上都可以接受请求,然后呈现适当的响应。所有试图混淆这种不连贯的现实的尝试都导致了较弱的网络框架,而不是更好的框架。

各种MVC框架主要执行所谓的“模型绑定”。 HTTP POST或GET不带有从类构造的“对象”;所有它真的有POST或GET变量和标题等。 MVC世界的模型绑定器基本上采用这些简单的参数,并根据预期的类类型(通常在控制器中定义,或按惯例)在运行中构建对象。然后,Controller允许您基于这些对象执行代码操作,并最终以View的形式发送回响应。

此时,您应该选择1-2个流行的MVC框架并学习他们的范例,而不是用自己的框架重新发明轮子。我碰巧在ASP.NET MVC中工作并喜欢它,但Ruby on Rails非常好。对于每种主要语言,可能有1-2个成熟,可靠的MVC框架,因此您应该从使用您熟悉的语言开始。

在熟悉现有的MVC框架之后,您就可以开始思考如何以不同的方式实现它,如果这是最终的结果。