Унаследованные классы ASP.NET MVC ModelBinding - PullRequest
2 голосов
/ 02 декабря 2009

У меня есть вопрос о связывании моделей в ASP.NET MVC (я использую MVC 2 preview 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();

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

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

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

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

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

Ответы [ 2 ]

6 голосов
/ 04 декабря 2009

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

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

1 голос
/ 03 декабря 2009

Ну, я думаю, что один из способов сделать это - создать подкласс класса 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.
   }
}
...