【问题标题】:Reflection: inconsistent framework behavior with GetRuntimeProperty methods反射:与 GetRuntimeProperty 方法不一致的框架行为
【发布时间】:2012-12-22 23:33:35
【问题描述】:

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

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

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 对象包含 Id 和 Name 属性定义的两个属性定义,而 nameProperty 包含 Name 属性定义。没想到的是idProperty 对象为空...

来自 .NET Framework,我猜这是 Microsoft 架构师的意图,但我必须说这看起来不像您真正期望发生的事情。我确实相信此类类似方法的行为应该相同,但似乎 GetRuntimeProperty 过滤器在 GetRuntimeProperties 不应用过滤器的公共属性上。

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

谢谢。

【问题讨论】:

  • 请记住,仅在商店应用程序中才需要使用它。所以你看到的是一种妥协,IInspectable 并不完全是一个丰富的界面。
  • 他们完全搞砸了新的反射 API。在很多方面都是一团糟,我什至不知道从哪里开始。

标签: c# reflection .net-4.5


【解决方案1】:

在内部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&lt;PropertyInfo&gt; 集合,让您通过 LINQ 过滤该集合。您可以选择公共、非公共或任何其他类型的属性。对于GetRuntimeProperty 返回的单个属性,您不需要这种灵活性,因此它在大多数常见用途中受到限制。

【讨论】:

  • 问题是:害羞是这样设计的。没有多大意义。对我来说似乎是一个设计错误。
  • 正如@Steven 所说,我实际上理解它在内部是这样编码的,但我不明白为什么这些方法的行为不同。我更新了我的问题以更清楚。谢谢。
  • @Ucodia , Steven - 我添加了解释和链接。如您所见,这是设计决策。如果需要非公有财产,使用LINQ获取typeof(ObjectBase).GetRuntimeProperties().Single(p =&gt; p.Name == "Id")
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-15
相关资源
最近更新 更多