当我尝试使用元数据类型与视图模型时,我得到InvalidOperationException

本文关键字:模型 InvalidOperationException 视图 数据类型 | 更新日期: 2023-09-27 18:04:40

我有一个具有某些属性的模型。我使用一个带有元数据类型的分离类来定义属性的需求。我还尝试使用相同的元数据类和只定义属性子集的视图模型。下面是一个简单的示例代码,用于说明情况:

[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; }
}
问题是,当razor引擎试图处理视图时,它抛出InvalidOperationException,并给出以下错误消息:

类型'ViewModelA'的关联元数据类型包含以下未知属性或字段:Property2。请确保这些成员的名称与主类型上的属性名称相匹配。

在我的理解中,这里的问题是元数据包含视图模型不包含的属性。但是,这样我就不能真正理解拥有元数据类的优点。所以我的问题是

1)是否有办法防止抛出这个异常?

2)如果不是,这种情况下最好的模式是什么?(比如使用一个模型,一个视图模型,它包含了模型属性的子集,通过保持DRY方法来定义数据注释)。

当我尝试使用元数据类型与视图模型时,我得到InvalidOperationException

MetadataTypeAttribute通常用于希望将元数据应用于自动生成的对象的情况。如果您要将元数据应用于对象本身,则在重新生成对象时它们将被覆盖。

这通常是通过分部类完成的。请看下面的例子。在本例中,您创建了一个与自动生成的类同名的空部分类,它的名称当然是相同的,但是您向它添加了MetadataType属性,并在其中包含嵌套的元数据类。

您通常不将此用于其他类,因为其他类必须具有相同(或超集)的属性。

// 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。