2012-01-19 69 views
1

在MVC 3中,我一直在重構我的控制器,以通過使用泛型來移除一些重複的代碼,但我現在試圖重構我的視圖,但似乎無法調整模型該視圖使用泛型。視圖如何使用使用泛型的模型?

這裏是我的重構的抽象基控制器的相關部分:

public abstract class CrudController<TEntity> : Controller where TEntity : Entity, INamedEntity, IOrderedEntity, IHasMembers, new() 
{ 
    private readonly IUnitOfWork _unitOfWork; 
    protected readonly IRepository<TEntity> Repository; 

    protected CrudController(IUnitOfWork unitOfWork) 
    { 
    _unitOfWork = unitOfWork; 
    Repository = _unitOfWork.RepositoryFor<TEntity>(); 
    } 

    public ActionResult Edit(int id) 
    { 
    return PartialView(Repository.FindById(id)); 
    } 

    // More actions here... 
} 

這裏是我的實際控制人(他們是因爲重構很基本的):

public class StatusController : CrudController<MemberStatus> 
{ 
    public StatusController(IUnitOfWork unitOfWork) : base(unitOfWork) 
    { 
    } 
} 

public class PositionController : CrudController<MemberPosition> 
{ 
    public PositionController(IUnitOfWork unitOfWork) : base(unitOfWork) 
    { 
    } 
} 

注意兩個MemberStatusMemberPosition implements'Entity,INamedEntity,IOrderedEntity,IHasMembers'

現在,這裏是我的編輯爲這兩個控制器,我想重構觀點:

@model MyApp.Domain.Entities.MemberStatus 
@using (Html.BeginForm("Save", @ViewContext.RouteData.Values["Controller"].ToString(), FormMethod.Post, new { id = "EntityForm" })) 
{ 
    @Html.Hidden("Id") 
    <label class="Name"> 
    <span>New Name:</span><br /> 
    @Html.EditorFor(x => x.Name) 
    </label> 
} 

@model MyApp.Domain.Entities.MemberPositions 
@using (Html.BeginForm("Save", @ViewContext.RouteData.Values["Controller"].ToString(), FormMethod.Post, new { id = "EntityForm" })) 
{ 
    @Html.Hidden("Id") 
    <label class="Name"> 
    <span>New Name:</span><br /> 
    @Html.EditorFor(x => x.Name) 
    </label> 
} 

你可以看到,意見幾乎是相同的,與聲明模型中的第一行除外。我想知道如何傳遞一個通用參數,就像我對控制器所做的那樣,我認爲(在我的天真中)看起來像下面這樣,但是這顯然不起作用。

@model <TEntity> where TEntity : Entity, INamedEntity, IOrderedEntity, IHasMembers, new() 

我如何重構這兩種觀點(通過把一個通用視圖在共享文件夾)將實現視圖中的非混凝土模型?任何建議表示讚賞。

僅供參考 - 我認爲(雖然我還沒有嘗試過),我可以用一個視圖模型,但我寧願不要有這樣做,在這種情況下(我將不得不實現從實體映射到每個實體的ViewModel,這有點違背了這個重構的目的)。

+0

爲什麼不能有一個抽象/基類,所有TEntity都會使用它? – lahsrah

+0

請不要在「C#MVC3 - Refactoring - 」等前加前綴。這就是標籤的用途,而且標題在沒有任何東西的情況下更具可讀性。 –

+1

只是一個提示,而不是從路由數據中查找控制器名稱,您可以傳遞null,它將在內部拉動控制器名稱。 –

回答

3

如果兩個模型都具有公共屬性,請在界面中使用這些屬性創建一個接口,然後讓這兩個模型實現該接口。現在創建一個強制鍵入該界面的視圖。另一種選擇僅僅是在運行時動態評估的弱類型視圖。

+0

感謝您的信息。我想我要去抽象類,但應該是同樣的原則。我很欣賞反饋! – bigmac

1
@model Entity 
@if (Model is INamedEntity) 
{ 
    @{ Html.RenderPartial("NamedEntityFields", (INamedEntity)Model); } 
} 
@if (Model is IOrderedEntity) 
{ 
    @{ Html.RenderPartial("OrderedEntityFields", (IOrderedEntity)Model); } 
} 

NamedEntityFields.cshtml:

@model INamedEntity 
@* put name specific fields here *@ 
2

你能不能有模型定義爲你使用任何一個接口,而不是它實現了許多接口的對象?:

@model INamedEntity 
@using (Html.BeginForm("Save", @ViewContext.RouteData.Values["Controller"].ToString(), FormMethod.Post, new { id = "EntityForm" })) 
{ 
@Html.EditorForModel() 
} 

對於這可以爲INamedEntity接口創建一個編輯器模板。