视图如何使用使用泛型的模型?

时间:2012-01-19 23:31:28

标签: c# asp.net-mvc asp.net-mvc-3 generics refactoring

在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)
  {
  }
}

请注意 MemberStatus MemberPosition 都实现'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()

如何重构这两个视图(通过在Shared文件夹中放置一个通用视图)来实现视图中的非具体模型?任何建议都表示赞赏。

仅供参考 - 我认为(虽然我没有尝试过)我可以使用ViewModel,但在这种情况下我不想这样做(因为我必须实现从每个实体的实体映射到ViewModel,这有点抵消了这个重构的目的。)

3 个答案:

答案 0 :(得分:3)

如果两个模型都具有公共属性,请在界面中创建具有这些属性的接口,然后使两个模型都实现该接口。现在创建一个强类型的视图到该接口。另一个选项只是一个在运行时动态评估的弱类型视图。

答案 1 :(得分:2)

您是否可以将模型定义为您使用的接口而不是实现许多接口的对象?:

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

为此,您可以为INamedEntity界面创建一个编辑器模板。

答案 2 :(得分: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 *@