Настроить пользовательский поставщик метаданных для ViewModel

У меня есть ViewModel, для которой нужно иметь возможность динамически устанавливать свойства метаданных. Например, я хотел бы иметь возможность настраивать DisplayName и сообщения об ошибках валидации, используя значение других свойств модели. Я планирую сделать это с пользовательским MetadataProvider, следуя статье Брэда Уилсона.

Я хочу, чтобы поставщик использовался только с выбранными моделями просмотра. Итак, мой вопрос, как мне это настроить? Я видел примеры использования ModelMetadataProviders.Current = new MyModelMetadataProvider(), но это, вероятно, будет использовать пользовательский поставщик для всех объектов классов модели. Можно ли настроить провайдера для одной ViewModel?

2 ответа

Решение

Я уверен, что смена поставщика метаданных текущей модели в ViewModel небезопасна, когда вы начнете привлекать на сайт нескольких пользователей, не говоря уже о потоке-безопасности. Возможно, вы сможете использовать метод атрибута, но вам все равно придется реализовать свой собственный ModelMetadataProvider и установить для него значение "Текущий" в начале вашего приложения, а затем проверить наличие определенных атрибутов и определить, нужно ли возвращать ModelMetaData, если их нет, а затем упасть. до базовой реализации. Хотя, если честно, то количество ограничений, о которых вы говорите, иметь дело только с выбранными моделями представлений, но не иметь права знать или тестировать эти модели представлений? Похоже, вы делаете что-то не так в другом месте...

ОБНОВЛЕНИЕ: Когда мне понадобился поставщик ModelMetadata, я создал поставщика, который выглядит примерно так...

public class MyMetadataProvider : DataAnnotationsModelMetadataProvider
{
    protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
    {
        if ((containerType != typeof(MyType))
            return base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName);

        //setup custom ModelMetadata here
    }
}

Ты не можешь

Тем не менее, вы можете выступать в качестве прокси для всех других моделей. Что-то вроде:

public class YourProvider<TViewModel>
{
    public YourProvider(InnerProvider provider) {}


    public ModelMetaData GetMetaData(SomeContext context)
    {   
        if (context.ModelType != typeof(TViewModel))
            return _innerProvider.GetMetaData(context);

        //Other logic here.

    }
}

И, наконец, назначьте его следующим образом:

ModelMetadataProviders.Current 
    = new MyModelMetadataProvider<CustomViewModel>(ModelMetadataProviders.Current);
Другие вопросы по тегам