2016-12-22 1 views
0

基本クラスからすべて継承するエンティティを処理できる汎用コントローラを作成しようとしています。ベースエンティティ用のASP.NET MVC汎用コントローラ

時点で、私は "部署" コントローラを有する:

public class DepartmentsController : BaseController 
{ 
    Departments model; 

    public virtual ActionResult Index() 
    {       
     model = new Departments(""); 
     return View("Index", model.SearchAsList()); 
    } 

    [HttpPost] 
    public virtual ActionResult Insert(Departments obj) 
    { 
     obj.Create(); 
     return RedirectToAction("Index"); 
    } 

    [HttpPost] 
    public virtual ActionResult Update(Departments obj) 
    { 
     obj.Update(); 
     return RedirectToAction("Index"); 
    } 

    public virtual ActionResult Edit(int id) 
    { 
     model = new Departments(""); 
     model.ID = id; 
     return View("Edit", model.SearchAsList()[0]); 
    } 

    public virtual ActionResult Details(int id) 
    { 
     model = new Departments(""); 
     model.ID = id; 
     return View("Details", model.SearchAsList()[0]); 
    } 

    public virtual ActionResult Delete(int id) 
    { 
     model = new Departments(""); 
     model.ID = id; 
     model.Delete(); 
     return RedirectToAction("Index"); 
    } 

} 

ベースコントローラ:

public class BaseController : Controller 
{ 
    public virtual ActionResult Create() 
    { 
     return View("Create"); 
    } 

} 

ならびにエンティティ及び基地エンティティ:

public class BaseEntity 
{ 
    public int Create { get; set; } 
} 

public class Department : BaseEntity 
{ 
    public int MySpecificMethod { get; set; } 
} 

をしかし、私はこれをより汎用的にして、Department Controller(および他のすべてのエンティティコントローラにはhaそれらが基本コントローラー内のアクションと異なる場合を除き、アクションは実行されません。 「作成」アクションは「部署」を参照しない唯一のものであるため、ベースコントローラーに追加しましたが、ベースに基づいたオブジェクトタイプを受け入れるように変更する方法は不明ですエンティティ。

私はあなたがクラスを通過できる例を見てきました。

public class DepartmentsController<T> : BaseController 
     where T: class 

しかし、私のインスタンス内の「T」は、私が「BaseEntity」から継承し、私はので、それは公共の機能ですアクセスできるようにしたい知っているクラスになります。

は私がすることの例を変更:

public class DepartmentsController<T> : BaseController 
     where T: BaseEntity 

そして今、「T」は、ベースエンティティの機能へのアクセスを持っている(例えば作成します)が、それは私から特定の機能にアクセスする方法の問題を与えます実際のDepartmentクラス(MySpecificMethodなど)

うまくいけば、私のコントローラーとベースコントローラーをどのように変更できるのか誰かが説明できることを願っています。

ありがとうございます!

+0

送信時に 'DefaultModelBinder'を' Department'( 'BaseEntity'のみ)にバインドすることができず、それぞれの継承された型ごとに(' @model xxx'宣言を使って)このアプローチは本当に意味をなさない。 –

+0

なぜあなたはすべての行動をバーチャルにしていますか?あなたはそれらを無効にするつもりですか? –

+0

はい私のモデルビューは基本エンティティではなく "Department"モデルを参照しますが、新しい "Address"エンティティを作成した場合、そのエンティティのコントローラは "Departments"コントローラと全く同じです。上記の "Departments"を "Address"に変更して掲載しました。これは、より効率的になるようリファクタリングされ、すべてのアクションがベースコントローラーに移されることを示唆しています。あなたはこれをどうやって行うのですか?私は苦労しているビットです! – ca8msm

答えて

0

これを行うには、バインディングステップ中に(つまり、サーバーに送信するパラメータによって)派生クラスの1つを選択できる必要があります。

次に、あなたが私の場合はこの方法に

protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType) 

、その後、あなたが欲しい派生クラスのインスタンスを作成することができるようになります...

をオーバーライドし、カスタムModelBinderを必要とし、I持っている:

public class AbstractC1 { . . . } 
public class DerivedC1 : AbstractC1 { . . . } 
public class DerivedC2 : AbstractC2 { . . . } 

その後、私のコントローラで:

public ActionResult MyAction([ModelBinder(typeof(CustomModelBinder))] AbstractC1 myData) { . . . } 

そして、私のModelBinder中:MyFactoryはリクエストのいくつかのパラメータに依存し、DerivedC1またはDerivedC2のいずれかを作成します

public class CustomModelBinder : DefaultModelBinder { 
    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType) { 
    AbstractC1 data = MyFactory.createDerivedClass(...); 
    return data; 
} 

ただし、これを使用すると、すべての派生型に対して1つの共通メソッドを使用できます。基本クラスとして使用するか、派生クラスにキャストするメソッドを見つける必要があります。

関連する問題