2016-03-29 9 views
1

私はバックエンドサービスに連絡するフロントエンドASP.NET MVC Webサイトを持っています。フロントエンドとバックエンドはDTOを使用して通信します。この汎用クラスはどのように実装しますか?

public class MyDto 
{ 
    public string Name {get;set;} 
} 

このDTOを私のウェブサイトのユーザーに直接表示したくないので、私は同じデータを取るビューモデルを作成しました。

public class MyViewModel 
{ 
    public string Name {get;set;} 
} 

ここで、これらのすべてのビューモデルについて、更新、投稿および他の方法はすべて同じです。すべてのビューモデルに対して同じコントローラアクションを再入力する代わりに、これらのすべてのメソッドを含む抽象コントローラを作成することにしました。

public interface IViewModelControllerActions<T> 
{ 
    IUpdateData<T> UpdateData { get; } //IUpdateData defined somewhere else 
    IUploadData<T> UploadData { get; } // IUploadData defined somewhere else 
    // definitions for other actions 
} 

私は私のviewmodelに追加:

public class MyViewModel : IViewModelControllerActions<MyDto> 
{ 
    public string Name {get;set;} 

    public IUpdateData<T> UpdateData { get { /* Do stuff to get UpdateData */ } } 
    public IUploadData <T> UploadData { get { /* Do stuff to get UploadData */ } } 
} 

と抽象コントローラ作成:

public abstract class ViewModelController<T>: Controller where T : IViewModelControllerActions<T> 
{ 
     [HttpPost] 
     public ActionResult Upload(T input) 
     { 
      // do stuff with T.UploadData to upload 
     } 

     [HttpPost] 
     public ActionResult Update(T input) 
     { 
      // do stuff with T.UpdateData to update 
     } 

     // other methods 
} 

をすべて私の見解モデルが同じ動作を持っているでしょうので、だから私は、インターフェイスを作りましたアイデアは次のとおりです:新しいdtoとviewmodelが導入されたとき、私はビューモデルにIViewModelControllerActionsインターフェースを実装するだけです:

public class MyNewCoolerViewModel : IViewModelControllerActions<MyNewCoolerDto> 
{ 
    public string Name {get;set;} 
    public string AnotherNewName {get;set;} 
    public int ANumber {get;set;} 

    public IUpdateData<T> UpdateData { get { /* Do stuff to get UpdateData */ } } 
    public IUploadData <T> UploadData { get { /* Do stuff to get UploadData */ } } 
} 

そして抽象的なものから継承する新しい空のコントローラを作成:

public class MyNewCoolerController : ViewModelController<MyNewCoolerViewModel> {} 

コントローラ内のすべてのロジックがすでに実装されるようにします。

型MyNewCoolerViewModelが ジェネリック型またはメソッドViewModelController < T>で型パラメータTとして使用することはできません。しかし、私はこのエラーメッセージが表示されます。 MyNewCoolerViewModelからIViewModelControllerActionsへの暗黙的な参照変換はありません< MyNewCoolerViewModel>

私はエラーメッセージを理解し、しかし、私はそれを修正する方法を理解していません。このセットアップはどのように動作させるのですか?

+0

答えに同意します。これは、MVCアーキテクチャを犠牲にして、これを過度に複雑にしているようです。あなたのモデルは更新/アップロードを処理するべきではありません。通常は、モデルとコントローラをよりシンプルに保ち、ビジネスレイヤー内の複雑さを管理することが最善です。 Automapperはオリジナルの課題を解決することもできます。 –

+0

私はこれを少し前に試してみましたが、MVCが汎用コントローラーベースをサポートしていないことがわかりました。変更されているかもしれませんが、Googleの価値があります。 –

答えて

0

あなたが見た/考えたAutomapperですか?

私はあなたがそれを過度に作成していると思っています - あなたの質問に直接答えは出ていませんが、DTO - > ViewModelの問題は通常、ある種のマッパーを使って解決されます。あなたのプロジェクトでそのアプローチに何が間違っていますか?

+0

チップをありがとう!しかし、Automapperが、新しいDTOとVMが追加されるたびに、新しいコントローラでUpdate、Uploadなどのメソッドを再入力しなければならないという問題を解決する方法はわかりません。 – ohyeah

0

これはパズルのような種類の感じが、しばらくの間、それを見た後、主な問題は、コントローラ内のTは、自己参照であるということである。この場合にはTがしなければならないことを意味

abstract class ViewModelController<T>: Controller where T : IViewModelControllerActions<T> 

タイプはIViewModelControllerActions<IViewModelControllerActions<T>>です。 コントローラは、あなたがそれ

を使用するしかし、正直に言うと、これは(IMO)MVCアーキテクチャと非常に良く一致していないつもり方法に応じ ViewModelController<T,U>:Controller where T:IViewModelController<U>または ViewModelController<IViewModelControllerAction<T>>のいずれかでなければなりません。コントローラおよび再利用のためとして、私は、あなたが全体IViewModelControllerActionインタフェースをスキップして、ちょうど、基本クラスのメソッドをオーバーライドすることができ、このような何かを考える:

public abstract class ViewModelController<T,U>:Controller{ public ActionResult Update(T item){...} public abstract void Save(U dto); }

Uは、あなたがしようとする方法に応じて、オプションであるかもしれませんしかし、それはスタートです。

関連する問題