2016-12-22 70 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」的操作,因此我已將其添加到基本控制器,但我不確定如何修改它以便它可以接受基於我的基礎的任何對象類型實體。

我看過一些例子,你可以通過一個類,例如

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

是的,我的模型視圖當然會引用「部門」模型而不是基本實體,但是如果我創建一個新的「地址」實體,則該實體的控制器將與「部門」控制器I完全相同張貼在上面,但「部門」更改爲「地址」。這表明可以將其重構爲更高效,並將所有操作轉移到基本控制器中。你如何做到這一點是我正在努力的一點! – ca8msm

回答

0

爲此,您需要能夠在綁定步驟(即通過發送給服務器的參數)中選擇一個派生類。

接下來,你需要一個自定義的模型綁定器,覆蓋方法

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

,然後,你就可以創建所需的派生類的一個實例...

在我的情況,我有:

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

然後,在我的控制器:

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

而且,在我的模型綁定器:

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

凡MyFactory創建要麼DerivedC1或DerivedC2,根據請求的一些參數。

但是...這允許您對所有派生類型使用一個通用方法,儘管您必須將它們用作基類,或者找到將它們轉換爲其派生類的方法。