我可以在同一个字段上多次使用IMetadataAware属性吗?

Kob*_*obi 7 c# modelmetadata data-annotations asp.net-mvc-3

我有不同的人应该看到不同名称的字段.

例如,假设我有以下用户类型:

public enum UserType {Expert, Normal, Guest}
Run Code Online (Sandbox Code Playgroud)

我实现了一个IMetadataAware属性:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class DisplayForUserTypeAttribute : Attribute, IMetadataAware
{
    private readonly UserType _userType;

    public DisplayForUserTypeAttribute(UserType userType)
    {
        _userType = userType;
    }

    public string Name { get; set; }

    public void OnMetadataCreated(ModelMetadata metadata)
    {
        if (CurrentContext.UserType != _userType)
            return;
        metadata.DisplayName = Name;
    }
}
Run Code Online (Sandbox Code Playgroud)

我的想法是,我可以根据需要覆盖其他值,但是当我不这样做时,可以使用默认值.例如:

public class Model
{
    [Display(Name = "Age")]
    [DisplayForUserType(UserType.Guest, Name = "Age (in years, round down)")]
    public string Age { get; set; }

    [Display(Name = "Address")]
    [DisplayForUserType(UserType.Expert, Name = "ADR")]
    [DisplayForUserType(UserType.Normal, Name = "The Address")]
    [DisplayForUserType(UserType.Guest, Name = "This is an Address")]
    public string Address { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

问题是当我有多个相同类型的属性时,DataAnnotationsModelMetadataProvider只运行OnMetadataCreated第一个属性.
在上面的示例中,Address只能显示为"地址"或"ADR" - 其他属性永远不会执行.

如果我尝试使用不同的属性- ,DisplayForUserType,DisplayForUserType2,DisplayForUserType3一切工作正常.

我在这里做错了吗?

Tom*_*her 11

我知道我在这个派对上有点迟了但是我正在寻找同样问题的答案而无法在网上找到它.最后我自己解决了.

简而言之,您可以拥有在同一字段/属性上实现IMetadataAware接口的多个相同类型的属性.您只需要记住在扩展它时覆盖Attribute类的TypeId并将其替换为为每个派生属性的每个实例提供唯一对象的东西.

如果不覆盖派生属性的TypeId属性,那么该类型的所有属性都将被视为相同,因为默认实现将属性的运行时类型作为id返回.

因此,以下内容现在可以按预期工作:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class DisplayForUserTypeAttribute : Attribute, IMetadataAware
{
    private readonly UserType _userType;

    public DisplayForUserType(UserType userType)
    {
        _userType = userType;
    }

    public override object TypeId
    {
        get
        {
            return this;
        }
    }

    public string Name { get; set; }

    public void OnMetadataCreated(ModelMetadata metadata)
    {
        if (CurrentContext.UserType != _userType)
            return;
        metadata.DisplayName = Name;
    }
}
Run Code Online (Sandbox Code Playgroud)