Есть ли причина, по которой связыватель моделей по умолчанию не привязывается к полям? - PullRequest
5 голосов
/ 19 декабря 2011

Я использую ASP.NET MVC3, и мне интересно, что связыватель моделей по умолчанию связывается с открытыми свойствами, но не с открытыми полями.

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

Вопрос: в чем причина?

Ответы [ 3 ]

2 голосов
/ 19 декабря 2011

но иногда я использую некоторые предопределенные классы, которые содержат некоторые поля

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

Итак, вернемся к основному вопросу: поля должны быть изменены только внутри данного класса.Они не должны быть доступны непосредственно снаружи.Они представляют и держат внутреннее состояние класса.С другой стороны, свойства - это то, что должно подвергаться воздействию внешнего мираПредставьте, что в свойстве getter / setter у вас есть некоторая пользовательская логика.При непосредственном изменении поля эта пользовательская логика будет нарушена и может привести объект в несогласованное состояние.

0 голосов
/ 08 сентября 2015

DefaultModelBinder предоставляет публичный метод: DefaultModelBinder.BindModel и ряд защищенных методов, доступных для переопределения. Все они перечислены здесь .

Помимо модели, этот метод относится только к свойствам, а не к полям, как

  • GetModelProperties
  • GetFilteredModelProperties,
  • GetPropertyValue
  • OnXYZValidating
  • OnXYZValidated
  • OnXYZUpdating
  • OnXYZUpdated
  • GetXYZValue,

, где XYZ означает Model, или Property/ies, или оба, и т. Д.

Как видите, с этими именами не упоминается Fields. Как объяснил Дарин , связыватель не допускает прямых изменений в состоянии модели. Следовательно, нет Field в его методах.

Также вы можете взглянуть на другой важный класс: ModelBindingContext . Экземпляр этого класса передается в BindModel,, а затем в BindSimpleModel, и BindComplexModel, в зависимости от типа модели (string, int, ... считаются простыми, все остальное сложно).

Итак, этот контекст имеет следующие свойства:

  • ModelXYZ и
  • PropertyXYZ.

Другими словами, у вас нет средств для ссылки на поля в вашей ViewModel, если вы не переопределяете эти классы и не предпринимаете специальных действий для этого.

Но опять же, остерегайтесь борьбы с фреймворком, за ним всегда легче следовать.

РЕДАКТИРОВАТЬ: Класс ModelMetadata содержит все данные, необходимые для привязки модели. Однако его код не показывает никаких признаков полей, имен полей и т. Д. Только ссылки на свойства и доступ к ним. Таким образом, даже если вы попытаетесь унаследовать и переопределить DefaultModelBinder и ModelBinderContext , вы все равно не сможете получить доступ к полям, не обращая внимания на то, что является их модификатором доступа: public, private и т. Д.

Надеюсь, это объясняет большую часть этого.

0 голосов
/ 19 декабря 2011

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

Хотя я думаю, что связыватель моделей использует кэш для повышения производительности.

...