2016-09-14 146 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; 
     } 
    } 
}