2010-04-09 29 views
4

我需要檢查,如果屬性已在其好友類特定屬性定義屬性:反思,得到DataAnnotation從哥們類

[MetadataType(typeof(Metadata))] 
public sealed partial class Address 
{ 
    private sealed class Metadata 
    { 
     [Required] 
     public string Address1 { get; set; } 

     [Required] 
     public string Zip { get; set; } 
    } 
} 

如何檢查哪些屬性定義Required屬性?

謝謝。

回答

8

它可以通過嵌套類型的探索來完成:

public IEnumerable<PropertyInfo> GetRequiredProperties() 
{ 
    var nestedTypes = typeof(Address).GetNestedTypes(BindingFlags.NonPublic); 

    var nestedType = nestedTypes.First(); // It can be done for all types 

    var requiredProperties = 
     nestedType.GetProperties() 
      .Where(property => 
          property.IsDefined(typeof(RequiredAttribute), false)); 

    return requiredProperties; 
} 

用例:

[Test] 
public void Example() 
{ 
    var requiredProperties = GetRequiredProperties(); 
    var propertiesNames = requiredProperties.Select(property => property.Name); 

    Assert.That(propertiesNames, Is.EquivalentTo(new[] { "Address1", "Zip" })); 
} 
+0

不錯!謝謝你。 – 2013-06-27 20:58:14

+1

儘管這樣做有效,但它對'夥伴'(元數據)類的關係給出了錯誤的假設,因爲它是通過屬性定義的。換句話說,一個理想的解決方案將檢查'MetadataTypeAttribute'的根類型以達到好友類型,而不是'GetNestedTypes()'。除非它們是嵌套的,否則此方法不適用於所有此類元數據類。它還會返回'RequiredAttribute's屬性,這些屬性在元數據類中沒有定義,這些屬性來自其他嵌套的類(如果它們存在的話) – JoeBrockhaus 2014-05-22 18:08:41

0

雖然不太優雅然後以利沙的解決方案,但它的工作原理也:)

你的屬性:

[AttributeUsage(AttributeTargets.All, AllowMultiple=false)] 
class RequiredAttribute : System.Attribute 
{ 
    public string Name {get; set; } 

    public RequiredAttribute(string name) 
    { 
     this.Name = name; 
    } 

    public RequiredAttribute() 
    { 
     this.Name = ""; 
    } 
} 

一些類:

class Class1 
{ 
    [Required] 
    public string Address1 { get; set; } 

    public string Address2 { get; set; } 

    [Required] 
    public string Address3 { get; set; } 
} 

用法:

Class1 c = new Class1(); 
RequiredAttribute ra = new RequiredAttribute(); 

Type class1Type = c.GetType(); 
PropertyInfo[] propInfoList = class1Type.GetProperties(); 
foreach (PropertyInfo p in propInfoList) 
{ 
    object[] a = p.GetCustomAttributes(true); 
    foreach (object o in a) 
    { 
     if (o.GetType().Equals(ra.GetType())) 
     { 
      richTextBox1.AppendText(p.Name + " "); 
     } 
    } 
} 
0

這裏是我的解決方案usinjg AssociatedMetadataTypeTypeDescriptionProvider

var entity = CreateAddress(); 
var type = entity.GetType(); 
var metadata = (MetadataTypeAttribute)type.GetCustomAttributes(typeof(MetadataTypeAttribute), true).FirstOrDefault(); 
var properties = new AssociatedMetadataTypeTypeDescriptionProvider(type, metadata.MetadataClassType).GetTypeDescriptor(type).GetProperties(); 
bool hasAttribute = HasMetadataPropertyAttribute(properties, "Name", typeof(RequiredAttribute)); 

private static bool HasMetadataPropertyAttribute(PropertyDescriptorCollection properties, string name, Type attributeType) 
{ 
    var property = properties[name]; 
    if (property == null) 
     return false; 

    var hasAttribute = proeprty.Attributes.Cast<object>().Any(a => a.GetType() == attributeType); 
    return hasAttribute; 
}