2012-12-22 46 views
8

當在新的.NET Framework 4.5中使用反射時,我遇到了一個奇怪的行爲,我發現這很奇怪。命名空間System.Reflection爲利用Type對象提供了一些新的擴展方法。其中兩個是GetRuntimeProperty(字符串名稱)和GetRuntimeProperties()。反思:使用GetRuntimeProperty方法的框架行爲不一致

現在想象一下,你有一個簡單的對象與一個內部屬性。

public class ObjectBase 
{ 
    protected int Id { get; set; } 
    public string Name { get; set; } 
} 

而你現在嘗試利用這種類型。

var properties = typeof(ObjectBase).GetRuntimeProperties(); 
// properties.Count = 2 

var idProperty = typeof(ObjectBase).GetRuntimeProperty("Id"); 
var nameProperty = typeof(ObjectBase).GetRuntimeProperty("Name"); 
// idProperty = null 
// nameProperty = System.String Name 

正如預期的properties對象持有的編號和名稱屬性defintions 2所屬性定義和nameProperty持有的名稱屬性定義。什麼不是預期的是idProperty對象是空的...

來自.NET框架,我猜這是微軟架構師的意圖,但我必須說,它似乎並不是你真正希望發生的事情。我確實相信這種類似的方法應該表現得一樣,但GetRuntimeProperty過濾GetRuntimeProperties不應用過濾器的公共屬性。

有沒有人有合理的解釋,爲什麼微軟決定這些類似的方法應該有不同的行爲?設計錯誤?

謝謝。

+0

請記住,只有在應用商店中才需要使用此功能。所以你所看到的是一種妥協,IInspectable並不完全是一個豐富的界面。 –

+0

他們完全搞砸了新的反射API。在很多方面這是一團糟,我甚至不知道從哪裏開始。 –

回答

3

內部GetRuntimeProperty調用Type.GetProperty(name)它使用指定的名稱搜索公共屬性。屬性Id受保護,因此無法找到。

public static PropertyInfo GetRuntimeProperty(this Type type, string name) 
{ 
    CheckAndThrow(type); 
    return type.GetProperty(name); 
} 

在另一方面GetRuntimeProperties回報公立和非公立性質

public static IEnumerable<PropertyInfo> GetRuntimeProperties(this Type type) 
{ 
    CheckAndThrow(type); 
    return type.GetProperties(BindingFlags.NonPublic | BindingFlags.Public | 
           BindingFlags.Static | BindingFlags.Instance); 
} 

Explanation:GetRuntimeProperties目的是恢復IEnumerable<PropertyInfo>集合中的所有屬性,讓你通過LINQ過濾該集合。您可以選擇公共,非公開或任何其他類型的屬性。使用GetRuntimeProperty返回的單個屬性,您不需要這種靈活性,因此它對最常見的用法是有限制的。

+4

問題是:害羞是這樣設計的。沒有多大意義。對我來說似乎是一個設計錯誤。 – Steven

+0

正如@Steven所說,我真的明白它在內部是這樣編碼的,但我不明白的是爲什麼這些方法的行爲不同。我更新了我的問題,以便更清楚。謝謝。 – Ucodia

+1

@Ucodia,史蒂文 - 我已經添加了解釋和鏈接。正如你所看到的,這是設計決定。如果你需要非公共屬性,使用LINQ來獲得它'typeof(ObjectBase).GetRuntimeProperties()。Single(p => p.Name ==「Id」)' –