Обработка подтипов в ASP.NET MVC - PullRequest
3 голосов
/ 21 февраля 2010

Я не могу придумать «лучший» способ справиться со следующей ситуацией - в основном, у меня есть набор хранимых объектов, которые наследуются от базового типа, и я хотел бы иметь возможность получить один из хранилища, найти его подтип (возможно, через «if (x is y)»), а затем действуйте соответствующим образом - некоторые используют общую реализацию, другие - с выделенной логикой и представлениями.

Полагаю, [урезано] это будет выглядеть примерно так:

/vehicle/details/1234

- Views
  - Vehicle
    - Details.aspx

abstract class Vehicle{
  public int ID{ get; }
}
class Motorbike : Vehicle{
  //whatever  
}
class Car : Vehicle{
  public int NoOfDoors{ get; }
}

class VehicleController : Controller{
  VehicleRepository _vehicleRepository; //injected, etc
  public ActionResult Details(int id){
    var vehicle = _vehicleRepository.Get(id);
    //we can now figure out what subtype the vehicle is
    //and can respond accordingly
  }
}

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

- Views
  - Vehicle
    - Details.aspx
    - CarDetails.aspx

public ActionResult Details(int id){
  var vehicle = _vehicleRepository.Get(id);
  return (vehicle is Car) ? DetailsView((Car)vehicle) : DetailsView(vehicle);
}
private ActionResult DetailsView(Car car){
  var crashTestResults = GetCrashTestResults(car);
  var carData = new CarDetailsViewData(car, crashTestResults);
  return View("CarDetails", carData);
}
private ActionResult DetailsView(Vehicle vehicle){
  var vehicleData = new VehicleDetailsViewData(car, crashTestResults);
  return View("Details", vehicleData);
}

Другим механизмом было бы использование подпапок на уровне представления, что обеспечивало бы разумную чистоту кода, но не помогало в моей ситуации, так как я тоже хочу метод настраиваемого действия ...

- Views
  - Vehicle
    - Car
      - Details.aspx
    - Motorbike
      - Details.aspx

public ActionResult Details(int id){
  var vehicle = _vehicleRepository.Get(id);
  return View(vehicle.GetType().Name + "\Details", vehicle);
}

В идеале решением было бы использование базового контроллера и выделенных контроллеров с переопределениями там, где это необходимо - но, поскольку нам нужно извлечь объект из хранилища, прежде чем мы сможем определить этот идеальный контроллер, я не могу понять, как заставить это работать. ..

Мои нынешние идеи обычно сводятся к первому препятствию, когда «VehicleController» слишком много знает о том, что такое переопределения подтипов, поэтому любые идеи будут оценены.

Приветствие.

Ответы [ 3 ]

0 голосов
/ 21 февраля 2010

Почему вы хотите создать новый контроллер для всех типов транспортных средств. В базе данных N-M ассоциация будет простой и гибкой.

VehicleTypes
    ->Id
    ->Name

VehicleTypeVariables
    ->Id
    ->Name

Vehicles
    ->Id
    ->VehicleTypeId

VehicleVariables
    ->Id
    ->VehicleId
    ->VehicleTypeVariableId
    ->Value
0 голосов
/ 21 февраля 2010

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

Логика контроллера, помимо этого различного вида, не выглядит так, как будто она должна быть разной 'для каждого типа транспортного средства. Вы на самом деле пытаетесь изменить поток программы в зависимости от типа транспортного средства, или контроллер в основном обрабатывает операции CRUD?

Предполагая, что вы просто пытаетесь изменить визуализированный вид, взгляните на функциональность DisplayFor и EditorFor для MVC 2. Это должно позволить вам передать только тип модели, а затем отобразить соответствующий вид (iirc, с ним немного поиграли).

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

0 голосов
/ 21 февраля 2010

Я вижу два решения, в зависимости от которых будет меньше дублирования:

1) У Транспортного средства есть абстрактные методы GetViewName и GetViewData, которые позволяют вам иметь несколько представлений, но ваш контроллер не должен знать о них.

2) Пусть Vehicle включает абстрактный метод GetViewData, который возвращает объект, содержащий все ViewData для этого класса. В этом случае ViewData будет реализовывать интерфейсы, и ваше единственное представление может составлять разделы HTML на основе if (ViewData is IHasCrashTestData) или чего-то подобного.

В большинстве случаев я бы предложил вариант 1 более расширяемый.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...