Reputation: 2302
I need to check if property has specific attribute defined in its buddy class:
[MetadataType(typeof(Metadata))]
public sealed partial class Address
{
private sealed class Metadata
{
[Required]
public string Address1 { get; set; }
[Required]
public string Zip { get; set; }
}
}
How to check what properties has defined Required
attribute?
Thank you.
Upvotes: 4
Views: 2390
Reputation: 2302
Here is my solution 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;
}
Upvotes: 0
Reputation: 4816
Although less elegant then Elisha's solution, but it works also :)
Your attribute:
[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 = "";
}
}
Some class:
class Class1
{
[Required]
public string Address1 { get; set; }
public string Address2 { get; set; }
[Required]
public string Address3 { get; set; }
}
Usage:
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 + " ");
}
}
}
Upvotes: 0
Reputation: 23790
It can be done using exploration of nested types:
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;
}
Usage example:
[Test]
public void Example()
{
var requiredProperties = GetRequiredProperties();
var propertiesNames = requiredProperties.Select(property => property.Name);
Assert.That(propertiesNames, Is.EquivalentTo(new[] { "Address1", "Zip" }));
}
Upvotes: 8