2016-09-14 147 views
3

也许不是最精确的标题,但它有点难以描述;也许你们可以帮我在这里?我正在使用MVC格式编写游戏,并且我希望每个基类(控制器,模型和视图)都具有对其伴随功能的引用,形成一种三角形(即,模型具有对控制器的引用定义它,并引用它大部分这些类的观点,等等)是这样的:通用类约束其中<T>是约束通用类的类型

public class Model { 
    public Controller controller; 
    public View view; 

    public void Connect (Controller controller, View view) { 
    this.controller = controller; 
    this.view = view; 
    } 
} 

这是正常的,但每当我打算拉起ChildModel的控制器,我需要投到相应的ChildController以获取正确的版本。我可以让一个实用方法/ getter来获取一个合适的投射物,但我宁愿不为每个孩子类重写这段代码。我以为我可以通过使基类的通用解决这个问题,但我现在运行到哪里,新的通用类需要的是试图定义它们的类引用的一个问题,因此:

public class Model<V, C> where V : View<?, C> where C : Controller<?, V> { 
    public Controller<?, V> controller; 
    public View<?, C> view; 

    public void Connect (Controller<?, V> controller, View<?, C> view) { 
    this.controller = controller; 
    this.view = view; 
    } 
} 

正如你可以看到,这很快就会在基类中变得混乱。我不知道用什么符号(参考上面的例子)试图定义约束的模型。将“模型”放入问号似乎也不能编译,因为我遇到了一个地狱般的拳击转换问题。

有没有办法完成我所追求的,或者我只是想在这里过于聪明?如果这可以工作,我很想能够与约束到他们的“三角”的类型声明子类,所以我能避免不必要的铸造或辅助方法:

public class ChildModel<ChildView, ChildController> { 

    public ChildModel() { 
    this.controller <- calls ChildController type, not base type! 
    } 
} 

人有什么想法?

+0

相关http://stackoverflow.com/a/25166761/380384和http://stackoverflow.com/a/4632320/380384 – ja72

回答

1

它看起来像你混淆了互动所有权。所有权意味着一方拥有另一方权利,而交互则意味着它们彼此沟通。 MVC主要定义三个参与者之间的交互,尽管您可以说视图和控制器都拥有一个模型。

enter image description here

在代码如图所示,类拥有的属性,因此控制器类拥有视图和视图拥有的控制器。

var model = new Model(); 
var view = new View<Controller<Model, View<Controller, Model>, ... 

这不适用于您希望的方式的泛型,因为交互变为循环。这是鸡和鸡蛋的问题:鸡来自鸡放的鸡蛋。通过赋予控制器对视图的所有权以及模型的控制器和视图所有权,我们可以解决大部分问题。

public class Model 
{ 
} 

public interface IView<M> 
{ 
    M Model { get; } 
} 

public class MyView : IView<Model> 
{ 
    public MyView(Model model) 
    { 
     Model = model; 
    } 

    public Model Model 
    { 
     get; 
    } 
} 

public interface IController<V, M> 
{ 
    M Model { get; } 
    V View { get; } 
} 

public class MyController : IController<MyView, Model> 
{ 
    public MyController(MyView view, Model model) 
    { 
     View = view; 
     Model = model; 
    } 

    public Model Model 
    { 
     get; 
    } 

    public MyView View 
    { 
     get; 
    } 
} 

我们仍然使用泛型要做到这一点,你可以很方便地访问大多数的信息,但至今没有引入循环引用。

class Program 
{ 
    public static void Main() 
    { 
     var model  = new Model(); 
     var view  = new MyView(model); 
     var controller = new MyController(view, model); 
    } 
} 

现在,如果你想确保视图有一个对控制器的引用,你可以通过属性来做到这一点。

view.Controller = controller; 

你可以不顾一切,我刚才给你看 - 去物业注射途径。这意味着不用通过构造函数来获取依赖关系,这会创建循环引用限制来创建对象,您可以简单地执行此操作。

var model = new Model(); 
var view = new View(); 
var controller = new Controller(); 

model.View = view; 
model.Controller = controller; 

view.Controller = controller; 
view.Model = model; 

controller.View = view; 
controller.Model = model; 

无论使用什么方法,诀窍是避免您在当前代码中存在的循环依赖性问题。大多数MVC框架提供了丰富的数据绑定,这些数据绑定打破了类之间的直接耦合,但是如果你没有这些,你必须写一些东西或找到某种东西,或者在语言规则的限制范围内工作。

有很多方法可以解决这个问题。当我写这篇文章的时候还有另外一个答案,所以你也应该看一下。

+0

侧面问题:您使用哪个程序或工具绘制该图表? –

+0

这是由http://yuml.me提供的免费服务 –

+0

非常感谢!我喜欢这个实现,我想我会继续前进。感谢的人:) – WTScott

0

这是我的建议。 1.您应该使用Controller作为您的MVC模式的主要部分。控制器应该从模式获取信息,处理它,然后调用视图。

这里是为控制器

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace Inheritance.Classes 
{ 
    public class Controller<T, U> where T : Model, new() where U : View, new() 
    { 
     protected T _model; 
     protected U _view; 

     public Controller() 
     { 
      this._model = new T(); 
      this._view = new U(); 
     } 

     public Controller(T model, U view) 
     { 
      this._model = model; 
      this._view = view; 
     } 

     public string ParentFunction() 
     { 
      return "I'm the parent"; 
     } 
    } 
} 

注意我的基类,我还有模型和视图的基类。由于它们目前是空的,我不会告诉你代码

然后,我可以定义我的子类。例如,我将创建一个PageController,PageModel和PageView。他们都会从他们的BaseClass继承。

注意:PageModel和PageView再次为空。它们只用于继承

PageController.cs

using Inheritance.Page; 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace Inheritance.Classes 
{ 
    public class PageController : Controller<PageModel, PageView> 
    { 
     public PageController():base() 
     { 

     } 

     public PageModel Model 
     { 
      get 
      { 
       return base._model; 
      } 
     } 
    } 
} 

因此,大家可以看到,你会指定Model类,只有里面的PageController View类。

要使用你的类,你可以根据以下步骤做:

 PageController controller = new PageController(); 

     //We can access the parent function 
     Console.WriteLine(controller.ParentFunction()); 

     //Function defined into the controller. 
     PageModel model = controller.Model; 
0

我想这是你想要的东西:

public class GameModel : Model 
{ 
    public int ID { get; set; } 
} 

public class GameView : View<GameModel, GameView> 
{ 
    public float FOV { get; set; } 
} 

public class GameController : GameView.BaseControler 
{ 
    // Set ID 
    public GameController() 
    { 
     Model.ID=100; 
     View.FOV=45f; 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var gm = new GameModel(); 
     var view = new GameView(); 
     var ctrl = new GameController(); 

     view.Connect(gm, ctrl); 

     Debug.WriteLine(view.Model.ID); 
    } 
} 

public class Model 
{ 

} 

public class View<TModel,TView> where TModel : Model where TView : View<TModel, TView> 
{ 
    public TModel Model { get; private set; } 
    public BaseControler Controler { get; private set; } 

    public void Connect(TModel model, BaseControler controler) 
    { 
     this.Model=model; 
     this.Controler=controler; 
     this.Controler.Connect(model, this as TView); 
    } 
    public class BaseControler 
    { 
     public TView View { get; private set; } 
     public TModel Model { get; private set; } 

     public void Connect(TModel model, TView view) 
     { 
      this.Model=model; 
      this.View=view; 
     } 
    } 
}