2010-02-05 52 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 + ">")); 
}