2010-02-05 47 views
18

所以在我的情况下,我正在使用反射来发现类的结构。我需要能够通过PropertyInfo对象找出属性是否是自动实现的属性。我认为反射API不公开这样的功能,因为自动属性是C#依赖的,但是有没有解决方法来获取这些信息?如何找出属性是否是反射的自动实现的属性?

回答

16

您可以检查getset方法是否标有CompilerGenerated属性。然后,您可以将其与查找包含属性名称和字符串"BackingField"CompilerGenerated属性标记的私有字段结合使用。

也许:

public static bool MightBeCouldBeMaybeAutoGeneratedInstanceProperty(
    this PropertyInfo info 
) { 
    bool mightBe = info.GetGetMethod() 
         .GetCustomAttributes(
          typeof(CompilerGeneratedAttribute), 
          true 
         ) 
         .Any(); 
    if (!mightBe) { 
     return false; 
    } 


    bool maybe = info.DeclaringType 
        .GetFields(BindingFlags.NonPublic | BindingFlags.Instance) 
        .Where(f => f.Name.Contains(info.Name)) 
        .Where(f => f.Name.Contains("BackingField")) 
        .Where(
         f => f.GetCustomAttributes(
          typeof(CompilerGeneratedAttribute), 
          true 
         ).Any() 
        ) 
        .Any(); 

     return maybe; 
    } 

这不是糊弄的证据,很脆,可能不便于携带,比方说,单声道。

+0

非常感谢杰森,反射都跟我一样在此期间:)早该想到这一点。 – Zoki 2010-02-05 21:02:28

+1

@ 3o4eTo:只是预先警告,这不是傻瓜证明,易碎,可能不能移动到单声道。 – jason 2010-02-05 21:07:34

+0

在属性上没有getter时也要处理异常。 – nawfal 2013-05-12 11:22:30

7

这应该这样做:

public static bool IsAutoProperty(this PropertyInfo prop) 
{ 
    return prop.DeclaringType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance) 
          .Any(f => f.Name.Contains("<" + prop.Name + ">")); 
} 

的原因是,自动性的后盾FieldInfoName财产会是什么样子:

<PropertName>k__BackingField 

由于字符<>将不会出现对于普通字段,具有这种类型命名的字段指向自动属性的后台字段。正如杰森所说,它仍然脆弱。

或者使其稍快一点,

public static bool IsAutoProperty(this PropertyInfo prop) 
{ 
    if (!prop.CanWrite || !prop.CanRead) 
     return false; 

    return prop.DeclaringType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance) 
          .Any(f => f.Name.Contains("<" + prop.Name + ">")); 
}