Унаследованные классы ASP.NET MVC ModelBinding

У меня есть вопрос о ModelBinding в ASP.NET MVC (я использую MVC 2 превью 2), связанный с наследованием.

Скажем, у меня есть следующие интерфейсы / классы:

interface IBase
class Base : IBase
interface IChild
class Child: Base, IChild

И у меня есть пользовательская модель подшивки BaseModelBinder.

Следующая работа отлично работает:

ModelBinders.Binders[typeof(Child)] = new BaseModelBinder();
ModelBinders.Binders[typeof(IChild)] = new BaseModelBinder();

Следующие не работают (при привязке к объекту типа Child):

ModelBinders.Binders[typeof(Base)] = new BaseModelBinder();
ModelBinders.Binders[typeof(IBase)] = new BaseModelBinder();

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

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

Заранее спасибо.

2 ответа

Решение

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

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

Ну, я думаю, один из способов сделать это подкласс ModelBindersDictionary Класс и переопределить метод GetBinders(Type modelType, bool fallbackToDefault).

public class CustomModelBinderDictionary : ModelBinderDictionary
{
    public override IModelBinder GetBinder(Type modelType, bool fallbackToDefault)
    {
        IModelBinder binder = base.GetBinder(modelType, false);

        if (binder == null)
        {
            Type baseType = modelType.BaseType;
            while (binder == null && baseType != typeof(object))
            {
                binder = base.GetBinder(baseType, false);
                baseType = baseType.BaseType;
            }
        }

        return binder ?? DefaultBinder;
    }
}

В основном обходите иерархию классов, пока не будет найдено связующее для модели или по умолчанию DefaultModelBinder,

Следующим шагом является принятие структуры CustomModelBinderDictionary, Насколько я могу судить, вам нужно выделить подкласс для следующих трех классов и переопределить свойство Binders: DefaultModelBinder, ControllerActionInvoker а также Controller, Вы можете предоставить свой собственный статический CustomModelBinders учебный класс.

Отказ от ответственности: это просто грубый прототип. Я не уверен, что это на самом деле работает, какие последствия это может иметь или это разумный подход. Возможно, вы захотите скачать код для фреймворка самостоятельно и поэкспериментировать.

Обновление:

Я думаю, что альтернативным решением было бы определить свой собственный CustomModelBindingAttribute,

public class BindToBase : CustomModelBinderAttribute
{
    public override IModelBinder GetBinder()
    {
        return new BaseModelBinder();
    }
}

public class CustomController
{
   public ActionResult([BindToBase] Child child)
   {
       // Logic.
   }
}
Другие вопросы по тегам