2016-09-14 12 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に渡して、正しいバージョンを取得します。適切にキャストされたアイテムを取得するためのユーティリティメソッド/ゲッターを作成することができましたが、各子クラスごとにこのコードを書き直すことはできません。私は、基底クラスは、ジェネリックを作ることで、この問題を解決することができると思ったが、今はそれゆえ、新たにジェネリッククラスはそれらを定義しようとしているクラスへの参照を必要とする問題に実行している:あなたのよう

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は主に3人の参加者の相互作用を定義しますが、ビューとコントローラーの両方がモデルを所有しているとも言えます。コードで

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. 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で内部のViewクラスを指定します継承のため

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; 
      } 
     } 
    } 
} 

を使用しています。

あなたのクラスを使用するには、次のように行うことができます。

 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; 
     } 
    } 
} 
関連する問題