2012-10-25 126 views
3

我正在构建我自己的属性库,并且我想检查属性级别是否有属性。目前,我有这个方法非常有效:用lambda表达式替换字符串作为属性名称

public static bool HasPropertyAttribute<T>(this object instance, string propertyName) 
    { 
     return Attribute.GetCustomAttributes(instance.GetType().GetProperty(propertyName), typeof(T), true).Any(); 
    } 

现在,我寻找到解决方案,让我渡过lambda表达式而不是字符串propertyName的。有一种优雅的方式做到这一点不增加这种方法成为两个通用类型的依赖,又名:

HasPropertyAttribute<T, TProperty>(...). 
+0

http://blog.slaks.net/2010/12/partial型推理功能于net.html – SLaks

回答

6

您可以使用Lambda表达式来解决编译时的性能基准。 (从Retrieving Property name from lambda expression修改后的代码)

public PropertyInfo GetPropertyInfo<TProperty>(
    Expression<Func<TProperty>> propertyLambda) 
{ 
    MemberExpression member = propertyLambda.Body as MemberExpression; 
    if (member == null) 
     throw new ArgumentException(string.Format(
      "Expression '{0}' refers to a method, not a property.", 
      propertyLambda.ToString())); 

    PropertyInfo propInfo = member.Member as PropertyInfo; 
    if (propInfo == null) 
     throw new ArgumentException(string.Format(
      "Expression '{0}' refers to a field, not a property.", 
      propertyLambda.ToString())); 

    return propInfo; 
} 

你并不需要使用它作为一个扩展方法(但如果你要适应它,你可以,但有一个源对象实例是没有必要的,除了写行)

public class Test 
{ 
    public string Prop { get; set; } 
} 

Test t = new Test(); 
PropertyInfo propInfo = GetPropertyInfo(() => t.Prop); 
Console.WriteLine(propInfo.Name + " -> " + propInfo.PropertyType); //Prop -> System.String 

编辑:如果你想有一些不错的语法和必须避免现有参考类型的对象,你可以这样做:

public static class TypedReflection<TSource> 
{ 
    public static PropertyInfo GetPropertyInfo<TProperty>(
     Expression<Func<TSource, TProperty>> propertyLambda) 
    { 
     MemberExpression member = propertyLambda.Body as MemberExpression; 
     if (member == null) 
      throw new ArgumentException(string.Format(
       "Expression '{0}' refers to a method, not a property.", 
       propertyLambda.ToString())); 

     PropertyInfo propInfo = member.Member as PropertyInfo; 
     if (propInfo == null) 
      throw new ArgumentException(string.Format(
       "Expression '{0}' refers to a field, not a property.", 
       propertyLambda.ToString())); 

     return propInfo; 
    } 
} 

,并调用它像:

PropertyInfo propInfo = TypedReflection<Test>.GetPropertyInfo(o => o.Prop); 

在这一点上,它很容易增加额外的类型化思考方法(get方法,字段等)

编辑:它仍然是八九不离十两个泛型类型的依赖,但它通过类型推断隐藏起来。我更喜欢第二个例子;至少需要指定声明类类型(因为您想要类型安全),但不需要对象实例。它也有好处(我怀疑你是在这之后的),如果你重命名属性,它会传播到这个代码获得PropertyInfo

0

我选择了这个解决方案,至少所有的代码:

public static bool HasPropertyAttribute<T, TProperty>(this T instance, Expression<Func<T, TProperty>> propertySelector, Type attribute) 
    { 
     return Attribute.GetCustomAttributes(instance.GetType().GetProperty((propertySelector.Body as MemberExpression).Member.Name), attribute, true).Any(); 
    } 

被调用是这样的:

var cc = new CustomClass(); 
cc.HasPropertyAttribute(x => x.Name, typeof(NullableAttribute))