2016-12-22 2 views
0

Я пытаюсь создать общий контроллер, который может обрабатывать объекты, которые все наследуют от базового класса.ASP.NET MVC Generic Controller для базового объекта

На данный момент у меня есть "отдел" контроллер:

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; } 
} 

Но я хочу сделать это более общим, чтобы диспетчер отдела (и все мои другие контроллеры предприятия не нуждались в га любые действия, если они не отличаются от действий в базовом контроллере. Действие «Создать» является единственным, которое не ссылается на «Департамент», поэтому я добавил его к базовому контроллеру, но я не уверен, как его изменить, чтобы он принял любой тип объекта, основанный на моей базе организация.

Я видел примеры, где вы можете пройти через класс, например.

public class DepartmentsController<T> : BaseController 
     where T: class 

Однако, «T» в моем случае было бы класс, который я знаю, наследует от «BaseEntity», и поэтому я хочу, чтобы иметь возможность получить доступ к его общественные функции.

Я изменил этот пример быть:

public class DepartmentsController<T> : BaseController 
     where T: BaseEntity 

И теперь «Т» имеет доступ к функциям базы сущностей (например, Create), но это дает мне проблему, как получить доступ к конкретным функциям из фактический класс отдела (например, MySpecificMethod).

Надеюсь, это имеет смысл, и кто-то может объяснить, как я могу изменить свой контроллер и базовый контроллер.

Спасибо!

+0

Поскольку «DefaultModelBinder» не сможет связываться с «Департаментом» (только «BaseEntity») при отправке, и каждое представление будет по-разному для каждого унаследованного типа (с соответствующим объявлением '@model xxx') , этот подход действительно не имеет смысла. –

+0

Почему у вас есть все ваши действия виртуальные? Вы собираетесь переопределить их? –

+0

Да, мои модели, конечно, будут ссылаться на модель «Департамент», а не на базовую сущность, однако, скажем, если я создам новый объект «Адрес», контроллер для этого объекта будет точно таким же, как контроллер «Департаменты» I выше, но с «Отделами» изменено на «Адрес». Это говорит мне о том, что он может быть реорганизован как более эффективный, и все действия перемещаются в базовый контроллер. Как вы это делаете, это бит, с которым я борюсь! – ca8msm

ответ

0

Для этого вам нужно выбрать один из ваших производных классов во время этапа привязки (то есть по параметрам, которые вы отправляете на сервер).

Далее вам нужно пользовательские ModelBinder, переопределение метода

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

И, на мой ModelBinder:

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

Где MyFactory создает либо DerivedC1 или DerivedC2, в зависимости от некоторых параметров запроса.

BUT ... это позволяет использовать один общий метод для всех производных типов, хотя вы должны использовать их в качестве базовых классов или найти метод для их перевода в производные классы.