代码之家  ›  专栏  ›  技术社区  ›  Feryt

反射,从buddy类获取DataAnnotation属性

  •  4
  • Feryt  · 技术社区  · 15 年前

    我需要检查属性是否在其伙伴类中定义了特定属性:

    [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

    3 回复  |  直到 15 年前
        1
  •  8
  •   Elisha    15 年前

    可以使用嵌套类型的探索来完成:

    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" }));
    }
    
        2
  •  0
  •   sventevit    15 年前

    虽然不如以利沙的解决方案优雅,但它也有效:)

    您的属性:

    [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 + " ");
            }
        }
    }
    
        3
  •  0
  •   Feryt    15 年前

    这是我的解决办法 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;
    }