Что “Func <возражают> modelAccessor” параметр для в DataAnnotationsModelMetadataProvider MVC?

Это - один из параметров, предоставленных методу CreateMetadata (который Вы переопределяете при расширении поддержки метаданных).

ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes,
                             Type containerType,
                             Func<object> modelAccessor, <<--THIS ONE
                             Type modelType,
                             string propertyName)

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

Entity ent = (Entity)modelAccessor(); // = Null

Если я неправильно понял, кто-либо может объяснить, что это - цель? Или альтернативно, как правильно использовать его?

Спасибо

12
задан UpTheCreek 5 August 2010 в 06:56
поделиться

2 ответа

Параметр modelAccessor не указывает на экземпляр объекта, а скорее является функцией, которая будет обращаться к некоторому атрибуту вашего объекта. Func «инкапсулирует метод, не имеющий параметров, и возвращает значение типа, указанного параметром TResult». Например, если у нас есть следующий класс:

public class Bar(){

    [DisplayName("I am Foo.")]
    public string Foo{get;}
}

Когда вызывается CreateMetaData, он будет создавать метаданные для свойства Foo, а modelAccessor будет функцией, которая возвращает значение Foo.

Я немного покопался и нашел способ добраться до экземпляра объекта, но это требует использования отражения. Вы можете сделать следующее, чтобы получить класс Bar в моем примере:

if (modelAccessor != null)
{
    //Use reflection to get the private field that holds the Bar object.
    FieldInfo container = modelAccessor.Target.GetType().GetField("container");

    //Invoke field on the modelAccessor target to get the instance of the Bar object.
    Bar myObject = (Bar)container.GetValue(modelAccessor.Target);
}

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

2
ответ дан 2 December 2019 в 22:37
поделиться

Изначально мы использовали это как «объектную модель», а не как «Func modelAccessor». Нам пришлось изменить его в конце цикла разработки MVC 2.

Цель состоит в том, чтобы отложить получение фактического значения модели до тех пор, пока вы не узнаете, что оно вам понадобится (то есть, пока вы не вызовете ModelMetadata.Model).

Проблема, которую он решает, на самом деле является довольно эзотерической проблемой, связанной с привязкой модели к классу LINQ to SQL, в котором есть ссылка на внешний ключ. Проблема в том, что если вы получили дочерний объект, который представлен отношениями внешнего ключа (что обычно означает задержку загрузки этого объекта), вам больше не разрешается выбирать новый дочерний объект, задав внешний ключ. ID собственности. Очень часто модель привязывает идентификатор внешнего ключа (а не всю сущность внешнего ключа) при привязке модели, но если бы мы получили объект сущности внешнего ключа (для целей заполнения класса ModelMetadata), эта привязка больше не будет быть законным и фактически генерировать исключение. Поскольку ModelMetadata используется для обоих направлений моделей - входящего, через привязку модели, и исходящего, через генерацию HTML, нам нужно было ввести уровень косвенного обращения, чтобы защитить вашу способность использовать его в обоих сценариях, не нарушая правил LINQ to SQL.

7
ответ дан 2 December 2019 в 22:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: