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

У меня есть модель с определенными свойствами. Я использую отдельный класс с MetadataType для определения требований к свойствам. Я также пытаюсь использовать тот же класс метаданных с моделью представления, определяющей только подмножество свойств. Это простой пример кода ситуации для пояснения:

[MetadataType(typeof(Metadata))]
class ModelA
{

    public class Metadata
    {
         [Required]
         public object Property1 { get; set; }

         [Required]
         public object Property2 { get; set; }

    }

    public int Property1 { get; set; }
    public int Property2 { get; set; }
}

[MetadataType(typeof(ModelA.Metadata))]
class ViewModelA
{
    public int Property1 { get; set; }
}

Проблема в том, что когда движок бритвы пытается обработать представление, он выдает InvalidOperationException со следующим сообщением об ошибке:

Связанный тип метаданных для типа «ViewModelA» содержит следующие неизвестные свойства или поля: Property2. Убедитесь, что имена этих элементов совпадают с именами свойств основного типа.

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

1) Есть ли способ предотвратить создание этого исключения?

2) Если нет, то какой шаблон лучше всего подходит для этой ситуации? (например, используя модель, модель представления, которая содержит подмножество свойств модели, определяя аннотации данных, сохраняя подход DRY).


person kexx    schedule 22.05.2014    source источник


Ответы (1)


Атрибуты MetadataTypeAttribute обычно используются в тех случаях, когда вы хотите применить метаданные к автоматически созданным объектам. Если бы вы применяли метаданные к самим объектам, они были бы перезаписаны при повторном создании объектов.

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

Обычно вы не используете это с другими классами, так как другие классы должны иметь идентичные (или надмножества) свойств.

// Do no edit this class as it is auto generated
public partial class ModelA
{
    public int Property1 { get; set; }
    public int Property2 { get; set; }
}

// This class can be edited
[MetadataType(typeof(ModelA.Metadata))]
public partial class ModelA
{
    public class Metadata
    {
         [Required]
         public object Property1 { get; set; }

         [Required]
         public object Property2 { get; set; }

    }
}

Итак, отвечая на ваши вопросы:

1) Нет, вы не можете предотвратить исключение, потому что метаданные должны описывать все свойства своего родительского класса, и если эти свойства не существуют, они выбрасываются.

2) Вам нужно будет создать альтернативные классы метаданных. Поскольку это такая же работа, как и создание автономной модели представления, нет никакой реальной пользы от использования классов друзей для моделей представлений, которые являются подмножествами.

Многие люди увлекаются концепцией DRY. Проблема в том, что каждая реализация программного обеспечения имеет конкурирующие требования. DRY часто противоречит принципу единой ответственности.

В любом случае, MetadataTypeAttribute на самом деле больше похож на хак, чтобы иметь дело с тем, как дизайнеры генерируют код. Если вы используете Code First, я бы настоятельно не рекомендовал использовать MetadataTypeAttribute.

person Erik Funkenbusch    schedule 22.05.2014
comment
Спасибо за Ваш ответ. Таким образом, MetadataType предназначен для автоматически сгенерированных классов, таких как первая структура базы данных. Однако я сначала использую код, поэтому такое решение кажется мне бесполезным. На самом деле я немного запутался, так как видел эту технику в учебнике по MVC (microsoftvirtualacademy.com/training-courses/), поэтому я не знаю, почему они вообще упомянули об этом. Возможно пересмотрю видео. - person kexx; 22.05.2014
comment
Я оставляю вопрос открытым, так как не совсем понимаю, что вы имеете в виду, создавая альтернативные классы метаданных. Моя цель здесь - использовать аннотации данных, и к нему относится автомат проверки, определяя при этом только ограничения, поэтому я все еще ищу для этого хорошее решение. - person kexx; 22.05.2014
comment
@kexx - я имею в виду, определить альтернативный класс метаданных только с Property1. Что, как я уже сказал, требует такой же работы, как и наличие автономной модели представления с собственными атрибутами данных. Что касается учебника, они, вероятно, сначала использовали его с базой данных или сначала с моделью. - person Erik Funkenbusch; 23.05.2014
comment
Обычно вы не используете это с другими классами, поскольку другие классы должны иметь идентичные (или расширенные) свойства. - хотелось бы, чтобы это было указано где-нибудь в документах. - person brichins; 28.03.2018