Как представление может использовать модель, которая использует дженерики? - PullRequest
1 голос
/ 20 января 2012

В 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()

Как я могу реорганизовать эти два представления (поместив общее представление в общую папку), которые бы реализовали в представлении неконкретную модель?Любые предложения приветствуются.

К вашему сведению - я думаю (хотя я не пробовал), что я мог бы использовать ViewModel, но я бы предпочел не делать этого в этом случае (поскольку я должен был бы реализовать отображение от сущностей к ViewModel для каждой сущности, что несколько ослабляет цель этого рефакторинга).

Ответы [ 3 ]

3 голосов
/ 20 января 2012

Если обе ваши модели имеют общие свойства, создайте интерфейс с этими свойствами в интерфейсе, а затем заставьте обе модели реализовать этот интерфейс. Теперь создайте представление, строго привязанное к этому интерфейсу. Другой вариант - просто представление со слабым типом, которое динамически оценивается во время выполнения.

2 голосов
/ 20 января 2012

Может быть, вы просто определили модель как тот интерфейс, который вы используете, а не как объект, который реализует много интерфейсов?

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

Для этого вы можете создать шаблон редактора для интерфейса INamedEntity.

1 голос
/ 20 января 2012
@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 *@
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...