Как я могу предоставить свой собственный ICustomTypeDescriptor в ASP.NET MVC? - PullRequest
4 голосов
/ 20 апреля 2011

Я работаю над небольшой библиотекой для ASP.NET MVC 3, которая должна обеспечить лучшее повторное использование метаданных модели и простое сопоставление сущностей данных с / на пользовательские модели представления.Для этого мне нужно иметь возможность предоставить собственную реализацию ICustomTypeDescriptor для трех различных областей интересов в ASP.NET MVC:

  1. Леса
  2. Проверка
  3. Привязка модели

Кажется, что это можно сделать, установив System.Web.Mvc.ModelMetadataProviders.Current для моего собственного CustomMetaDataProvider, но этого недостаточно для охвата всех трех пунктов выше.

Проблема в том, что в System.Web.Mvc есть несколько классов, которые обращаются непосредственно к этому System.Web.TypeDescriptorHelper, который не расширяется, потому что выглядит так:

internal static class TypeDescriptorHelper {
        public static ICustomTypeDescriptor Get(Type type) {
            return new AssociatedMetadataTypeTypeDescriptionProvider(type).GetTypeDescriptor(type);
        }
    } 

Единственное решениеЯ обнаружил, что это очень неудобно, и для его работы требовалось создать много типов из System.Web.Mvc.Мне даже пришлось полностью перестроить CustomModelBinderDictionary только для того, чтобы перезаписать одну или две строки кода.Так что это работает, но это очень грязный взлом, и, вероятно, он сломается при следующем обновлении до новой версии ASP.NET MVC.

Итак, вот что я хотел бы знать : Я пропустил какой-нибудь простой способ сделать это?

Бонусный вопрос : Если нет, и вы из команды MVC, можете ли вы создать соответствующую точку расширения в MVC 4; -)?

Редактировать: В ответ на вопрос, почему мне нужно кодировать свой собственный TypeDescriptor: Для этого есть несколько причин: 1. Самое важное: мне нужно обойти проблему, описанную в https://forums.asp.net/t/1614439.aspx/1 2. Также янеобходимо динамически вставлять метаданные по разным причинам.Например, я хочу закодировать свой собственный атрибут Bind, но BindAttribute запечатан.Таким образом, вместо того, чтобы выводить из него, я динамически испускаю соответствующий BindAttribute из TypeDescriptor при обнаружении моей собственной реализации атрибута связывания.

Ответы [ 2 ]

1 голос
/ 29 апреля 2011

По словам Брэда Уилсона (члена команды ASP.NET MVC), эта проблема была включена в список ошибок для MVC 4. Поэтому, похоже, на данный момент нет хорошего решения, но, надеюсь, этобудет решена, когда выйдет MVC 4.

Для всех, кто интересуется моей библиотекой для многократного использования валидации и создания метаданных, а также для сопоставления модели / модели представления, смело подписывайтесь на мой блог на https://devermind.wordpress.com/. Я собираюсь выпустить библиотеку там.

0 голосов
/ 26 апреля 2011

Я не уверен, что вы пытаетесь сделать с помощью пользовательских реализаций Validation, ModelBinding и, возможно, ModelMetadata, чего нельзя сделать с помощью функциональности DependencyResolver в MVC?

Новыйподдержка лесов в недавнем обновлении Tooling Update для MVC 3 может удовлетворить ваши потребности в строительных лесах;однако я хотел бы взглянуть на возможное подключение к функциональности DependencyResolver для ModelBinding, ModelMetadata и Validation и посмотреть, смогут ли они достичь того, что вы ищете.Недавно у меня была похожая ситуация, когда мне нужно было реализовать многие из этих вариантов поведения с нуля, чтобы обеспечить гибкую структуру, и я смог сделать это только с поставщиками ModelMetadata и Validation, использующими IoC.В некоторых случаях я также унаследовал DynamicObject (или ExpandoObject), чтобы обеспечить еще большую гибкость.Я знаю, что это не совсем прямой ответ, но я не уверен, зачем вам нужен доступ к чему-то более низкому, чем эти точки расширения?

РЕДАКТИРОВАТЬ: Если вы хотите использовать повторноModelMetadata в похожих ViewModels, чтобы избежать необходимости переопределять одни и те же ModelMetadata в нескольких местах, вы можете рассмотреть последствия этого.Во многих случаях вам нужны определенные ограничения данных для ваших сущностей, но эти ограничения должны быть в DataModel, а не в ViewModel.Пользователь может иметь немного более строгие правила.Например, вы можете указать, что определенные поля доступны только для пользователя в ViewModel, но что сущность, используемая в качестве DataModel, позволяет вам изменять значение (как правило, из вашего кода).Точно так же вы можете столкнуться с ситуациями, когда ModelMetadata, использованный для создания представления Create для VideModel, может немного отличаться от ViewModel, используемого для представления Edit.Повторное их использование может показаться отличным способом сохранения согласованности и сокращения дублирования кода, но об этом вы можете пожалеть позже.Недавно я столкнулся с той же проблемой, где я хотел избежать написания новой ViewModel для каждого представления, которое может вызвать обратную передачу, я не нашел идеального решения, которое мне нравится, но я думаю, что повторное использование ModelMetadata вызовет больше проблем, которые он может решить вмое мнение.Написание ViewModels для представлений, которые в них нуждаются, также, вероятно, избавит вас от необходимости реализовывать собственную реализацию BindAttribute и проблему Scaffolding.Если я прав, предполагая, что не нужно создавать так много ViewModel с их собственными метаданными, это то, что заставляет вас пытаться найти реализации пользовательского BindAttribute, пользовательского Scaffolding, пользовательского ModelMetadata, пользовательского Validation и пользовательского ModelBinding ... это может стоитьпосмотрим, сколько времени на самом деле потребуется, чтобы просто создать ViewModels.

Если вы найдете лучший подход, не стесняйтесь, дайте мне знать: -)

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