I've built a method that returns me an instance of attribute if it is found on the property:
public static U GetPropertyAttribute<T, TProperty, U>(this T instance, Expression<Func<T, TProperty>> propertySelector, U attribute) where U : Attribute
{
return Attribute.GetCustomAttribute(instance.GetType().GetProperty((propertySelector.Body as MemberExpression).Member.Name), typeof(U), true) as U;
}
In order to get instance, I have to invoke:
var cc = new CustomClass();
cc.GetPropertyAttribute(x => x.Name, new NullableAttribute())
And it works fine, I get exact instance of the attribute class.
However, I don't like that I have to use new NullableAttribute() as parameter, I'd like to have invoke look like:
cc.GetPropertyAttribute<NullableAttribute>(x => x.Name)
This however does not work due to the fact that as soon as I remove second parameter and add 1 generic type in method name, it starts to require other two as well. Is there a way to force the method to infer 2 out of 3 generic parameters? I.e. I want to specify attribute class, but don't want to specify class name and property name.
UPDATE:
Here's the implemented code, thanks to Jon, as well as the code for string solution. I've decided to nest the class so that I don't polute the namespace if I introduce same approach for some other extension classes.
public static class AttributeExtensions
{
public static ObjectProperty<T, TProperty> From<T, TProperty>(this T instance, Expression<Func<T, TProperty>> propertySelector)
{
return new ObjectProperty<T, TProperty>(instance, propertySelector);
}
public class ObjectProperty<T, TProperty>
{
private readonly T instance;
private readonly Expression<Func<T, TProperty>> propertySelector;
public ObjectProperty(T instance, Expression<Func<T, TProperty>> propertySelector)
{
this.instance = instance;
this.propertySelector = propertySelector;
}
public U GetAttribute<U>() where U : Attribute
{
return Attribute.GetCustomAttribute(instance.GetType().GetProperty((propertySelector.Body as MemberExpression).Member.Name), typeof(U), true) as U;
}
}
public static T GetPropertyAttribute<T>(this object instance, string propertyName) where T : Attribute
{
return Attribute.GetCustomAttribute(instance.GetType().GetProperty(propertyName), typeof(T), true) as T;
}
}
So invoke now goes like this:
var cc = new CustomClass();
var attr = cc.From(x => x.Name).GetAttribute<NullableAttribute>();
MemberInfo
, so I can handle the same thing just calling something likeobj.GetType().GetProperty("MyProperty").GetAttribute<MyAttribute>()
. I understand that OP is using an expression because its advantages in terms of refactoring, but... – Pantaloon