反思:使用GetRuntimeProperty方法的框架行为不一致

Uco*_*dia 8 c# reflection .net-4.5

在新的.NET Framework 4.5中使用反射时,我遇到了一个奇怪的行为,我发现这是非常意外的.命名空间System.Reflection为利用Type对象提供了一些新的扩展方法.其中两个是GetRuntimeProperty(字符串名称)和GetRuntimeProperties().

现在假设你有一个带有内部属性的简单对象.

public class ObjectBase
{
    protected int Id { get; set; }
    public string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

而你现在尝试利用这种类型.

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
Run Code Online (Sandbox Code Playgroud)

正如所料,该properties对象包含Id和Name属性定义的两个属性定义,而nameProperty保存Name属性定义.没想到的是idProperty对象为null ...

来自.NET Framework,我想这是微软架构师的意图,但我必须说这似乎不是你真正希望发生的事情.我相信这些类似的方法应该表现相同,但似乎GetRuntimeProperty过滤公共属性,其中GetRuntimeProperties不应用任何过滤器.

有没有人有合理的解释为什么微软决定那些类似的方法应该有不同的行为?设计错误?

谢谢.

Ser*_*kiy 5

内部GetRuntimeProperty调用Type.GetProperty(name),搜索具有指定名称的公共属性。财产Id受到保护,因此无法找到。

public static PropertyInfo GetRuntimeProperty(this Type type, string name)
{
    CheckAndThrow(type);
    return type.GetProperty(name);
}
Run Code Online (Sandbox Code Playgroud)

另一方面GetRuntimeProperties返回公共和非公共属性

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

说明: GetRuntimeProperties目的是返回IEnumerable<PropertyInfo>所有属性的集合,让您可以通过LINQ过滤该集合。您可以选择公共、非公共或任何其他类型的属性。对于返回的单个属性,GetRuntimeProperty您不需要这种灵活性,因此它仅限于大多数常见用途。

  • 问题是:害羞是这样设计的吗?没有多大意义。对我来说似乎是一个设计错误。 (5认同)
  • @Ucodia,史蒂文 - 我添加了解释和链接。正如您所看到的,这是设计决策。如果您需要非公共属性,请使用 LINQ 获取`typeof(ObjectBase).GetRuntimeProperties().Single(p =&gt; p.Name == "Id")` (2认同)