I use the following code to get attributes from DataAnnotations:
public static T GetAttributeFrom<T>(this object instance, string propertyName) where T : Attribute
{
var attrType = typeof(T);
var property = instance.GetType().GetProperty(propertyName);
return (T)property .GetCustomAttributes(attrType, false).First();
}
Thanks to user: jgauffin
I want to improve his solution by pass a lambda expression instead a string:
public static T GetAttributeFrom<T>(this object instance, Expression<Func<T>> propertyExpression) where T : Attribute
{
var attrType = typeof(T);
var property = instance.GetType().GetProperty(GetPropertyNameFromLambdaExpression(propertyExpression));
return (T)property.GetCustomAttributes(attrType, false).First();
}
and my method to get the real property name from this expression:
public static string GetPropertyNameFromLambdaExpression<T>(Expression<Func<T>> propertyAsExpression)
{
var memberExpression = propertyAsExpression.Body as MemberExpression;
var propertyInfo = memberExpression.Member as PropertyInfo;
if (memberExpression != null && propertyInfo != null)
{
return memberExpression.Member.Name;
}
throw new ArgumentException(propertyAsExpression.ToString());
}
If I try something like this:
var id = this.GetAttributeFrom<RangeAttribute>(()=> Id).Maximum;
I get this error:
Cannot convert expression type 'int' to return type 'RangeAttribute'
How can I fix this?
You are using the generic type T as a type of the attribute and the property at the same time. Try to start with:
public static T GetAttributeFrom<T>(this object instance, string propertyName) where T : Attribute {
var attrType = typeof(T);
var property = instance.GetType().GetProperty(propertyName);
return (T)property.GetCustomAttributes(attrType, false).First();
}
public static T GetAttributeFrom<T, U>(this object instance, Expression<Func<U>> propertyExpression) where T : Attribute {
var attrType = typeof(T);
var property = instance.GetType().GetProperty(GetPropertyNameFromLambdaExpression<U>(propertyExpression));
return (T)property.GetCustomAttributes(attrType, false).First();
}
public static string GetPropertyNameFromLambdaExpression<U>(Expression<Func<U>> propertyAsExpression) {
var memberExpression = propertyAsExpression.Body as MemberExpression;
var propertyInfo = memberExpression.Member as PropertyInfo;
if (memberExpression != null && propertyInfo != null) {
return memberExpression.Member.Name;
}
throw new ArgumentException(propertyAsExpression.ToString());
}
then you can call this in this way:
var max = this.GetAttributeFrom<RangeAttribute, int>(() => Id).Maximum;
You can't ommit the second type (GetAttributeFrom<RangeAttribute>(() => Id)): C# generics can't infer second parameter?.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With