Как внедрить пользовательские свойства ModelMetadata и использовать их в помощниках HTML - PullRequest
2 голосов
/ 10 февраля 2011

Идея (упрощенная) состоит в том, чтобы пользователь определял свойства во ViewModel, содержащиеся в словаре.Что-то вроде этого:

public class MyViewModel
{
    [Required]
    public string Name { get; set; }

    [DisplayName("User address")]
    public string Address { get; set; }

    // ...

    public IDictionary<string, string> MetaData { get; set; }
}

Предположим, что метаданные содержат несколько дополнительных свойств : PhoneNumber, Email и т. Д., К которым вы можете получить доступ с помощью myViewModel.MetaData["PhoneNumber"].

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

Итак, вПомимо использования стандартных свойств как:

Html.TextBox("Name")

Я также хотел бы использовать эти дополнительные свойства:

Html.TextBox("PhoneNumber")

Мои исследования привели меня к наследованию от DataAnnotationsModelMetadataProvider (так как необходимотакже поддерживают стандартные атрибуты DataAnnotations для стандартных свойств) и пытаются выяснить, что именно там нужно переопределить, чтобы добавить дополнительных свойств в качестве дополнительных элементов ModelMetadata, но я немного застрял.

Я на правильном пути?Любой дополнительный указатель, который мог бы помочь мне здесь?

Спасибо

1 Ответ

2 голосов
/ 10 февраля 2011

Альтернативным вариантом может быть создание динамического объекта, подобного ViewBag / ViewData в MVC 3. У вас будет объект, к которому вы можете получить доступ через Model.MetaData.Foo, а Foo будет фактически отображаться на ключ в вашем словаре.

Тип, поддерживающий объект ViewBag: System.Web.Mvc.DynamicViewDataDictionary ;этот класс является внутренним и запечатанным, поэтому вам придется сделать его индивидуальную реализацию (если нет лучшего варианта, о котором я не знаю).Быстрый взгляд на источники MVC 3 показал следующее:

internal sealed class DynamicViewDataDictionary : DynamicObject {
    private readonly Func<ViewDataDictionary> _viewDataThunk;

    public DynamicViewDataDictionary(Func<ViewDataDictionary> viewDataThunk) {
        _viewDataThunk = viewDataThunk;
    }

    private ViewDataDictionary ViewData {
        get {
            ViewDataDictionary viewData = _viewDataThunk();
            Debug.Assert(viewData != null);
            return viewData;
        }
    }

    // Implementing this function improves the debugging experience as it provides the debugger with the list of all
    // the properties currently defined on the object
    public override IEnumerable<string> GetDynamicMemberNames() {
        return ViewData.Keys;
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result) {
        result = ViewData[binder.Name];
        // since ViewDataDictionary always returns a result even if the key does not exist, always return true
        return true;
    }

    public override bool TrySetMember(SetMemberBinder binder, object value) {
        ViewData[binder.Name] = value;
        // you can always set a key in the dictionary so return true
        return true;
    }
}

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

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