[英]Can I use an IMetadataAware attribute multiple times on the same field?
我有不同的人應該看到不同名稱的字段。
例如,假設我有以下用戶類型:
public enum UserType {Expert, Normal, Guest}
我實現了一個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;
}
}
我的想法是,我可以根據需要覆蓋其他值,但是當我不這樣做時,可以使用默認值。 例如:
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; }
}
問題是當我有多個相同類型的屬性時, DataAnnotationsModelMetadataProvider
只為第一個屬性運行OnMetadataCreated
。
在上面的示例中, Address
只能顯示為“Address”或“ADR” - 其他屬性永遠不會執行。
如果我嘗試使用不同的屬性 - DisplayForUserType
, DisplayForUserType2
, DisplayForUserType3
,一切都按預期工作。
我在這里做錯了嗎?
我知道我在這個派對上有點遲了但是我正在尋找同樣問題的答案而無法在網上找到它。 最后我自己解決了。
簡而言之,您可以擁有在同一字段/屬性上實現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;
}
}
您的實現沒有錯,但實現IMetadataAware
任何屬性都是在創建元數據后由AssociatedMetadataProvider (以及任何派生類型)應用的。 要覆蓋默認行為,您可以實現自定義ModelMetadataProvider
。
這是另一種替代快速解決方案:
從DisplayForUserType
類中刪除IMetadataAware
接口。
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class DisplayForUserTypeAttribute : Attribute//, IMetadataAware
{
//your existing code...
}
定義一個新的IMetadataAware
屬性,該屬性將按UserType應用顯示邏輯,如下所示:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class ApplyDisplayForUserTypeAttribute : Attribute, IMetadataAware
{
private readonly string _property;
public ApplyDisplayForUserTypeAttribute(string property)
{
this._property = property;
}
public void OnMetadataCreated(ModelMetadata metadata)
{
var attribues = GetCustomAttributes(metadata.ContainerType
.GetProperty(this._property), typeof(DisplayForUserTypeAttribute))
.OfType<DisplayForUserTypeAttribute>().ToArray();
foreach (var displayForUserTypeAttribute in attribues)
{
displayForUserTypeAttribute.OnMetadataCreated(metadata);
}
}
}
模型將是:
public class Model
{
[Display(Name = "Age")]
[DisplayForUserType(UserType.Guest, Name = "Age (in years, round down)")]
[ApplyDisplayForUserType("Age")]
public string Age { get; set; }
[Display(Name = "Address")]
[DisplayForUserType(UserType.Expert, Name = "ADR Expert")]
[DisplayForUserType(UserType.Normal, Name = "The Address Normal")]
[DisplayForUserType(UserType.Guest, Name = "This is an Address (Guest)")]
[ApplyDisplayForUserType("Address")]
public string Address { get; set; }
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.