【问题标题】:GetCustomAttributes vs GetCustomAttributesDataGetCustomAttributes 与 GetCustomAttributesData
【发布时间】:2017-11-08 16:04:58
【问题描述】:

我正在尝试找出从属性中获取自定义属性的最佳方法。我一直在为此使用GetCustomAttributes(),但我最近读到GetCustomAttributes() 导致创建属性的实例,GetCustomAttributesData() 只是获取有关属性的数据,而无需创建属性的实例。

考虑到这一点,GetCustomAttributesData() 似乎应该更快,因为它不会创建属性的实例。但是,我在测试中没有看到这个预期的结果。当循环遍历类中的属性时,第一次迭代让GetCustomAttributes() 运行大约 6 毫秒,GetCustomAttributesData() 运行大约 32 毫秒。

有谁知道为什么GetCustomAttributesData() 运行时间更长?

我的主要目标是测试属性是否存在并忽略包含该属性的任何属性。我并不特别关心我最终使用哪种方法,除了了解为什么GetCustomAttributesData()GetCustomAttributes() 慢之外,我并不真正关心这两种方法返回什么。

这是我用来测试的一些示例代码。我通过注释掉一个然后另一个独立地测试了这些 if 语句。

public static void ListProperties(object obj)
{
    PropertyInfo[] propertyInfoCollection = obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);

    foreach (PropertyInfo prop in propertyInfoCollection)
    {
        // This runs around 6ms on the first run
        if (prop.GetCustomAttributes<MyCustomAttribute>().Count() > 0)
            continue;

        // This runs around 32ms on the first run
        if (prop.GetCustomAttributesData().Where(x => x.AttributeType == typeof(MyCustomAttribute)).Count() > 0)
            continue;

        // Do some work...
    }
}

public class MyCustomAttribute : System.Attribute
{
}

前段时间,看了this的帖子,决定试试IsDefined()的方法。它似乎比GetCustomAttributes()GetCustomAttributesData() 都快。

if (prop.IsDefined(typeof(MyCustomAttribute)))
    continue;

【问题讨论】:

  • 这里的问题是这些方法返回了什么。您在测试中似乎并不关心这一点,但我很确定自定义属性实例与CustomAttributeData 不同。你打算怎么用它?
  • GetCustomAttributeData 的文档建议“使用此方法检查仅反射上下文中代码的自定义属性,如果自定义属性本身是在加载到仅反射上下文”。我个人会遵循这个建议。
  • “我的主要目标是测试一个属性的存在并忽略任何包含该属性的属性。”也许改用IsDefinedif (prop.IsDefined(typeof(MyCustomAttribute), true))(或false,如果您不想涉及继承)
  • 我已经编辑了我的问题。感谢@JonSkeet 的建议。我将使用 IsDefined()。
  • 继承在您的示例中不起作用,@JonSkeet。请参阅stackoverflow.com/q/38565778/2157640 System.Attribute 的静态方法或 System.Reflection.CustomAttributeExtensions 的扩展必须使用。

标签: c# .net reflection


【解决方案1】:

GetCustomAttributesData 也会创建新对象的实例,而不是属性本身。它创建CustomAttributeData 的实例。这个类主要有关于属​​性类型的信息,还有关于构造函数和构造函数参数的信息,甚至还有构造函数参数的名称。

这些属性必须使用反射来设置,而创建属性实例只是标准的对象创建。当然这一切都取决于你的属性的构造函数有多复杂,虽然一般我很少看到复杂的属性。

因此,调用GetCustomAttributesData 可以为您提供比GetCustomAttributes 更多/不同的属性信息,但(对于简单属性)操作成本更高。

但是,如果您打算在同一个 MemberInfo 对象上多次调用 GetCustomAttributesData,它可能会更快,因为反射调用通常会被缓存。但我没有对此进行基准测试,所以请稍加注意。

【讨论】:

  • 感谢有关 GetCustomAttributesData() 的信息。我没有意识到正在创建另一个对象。我已经更新了我的问题并决定使用 IsDefined()。
猜你喜欢
  • 2015-08-18
  • 2021-12-01
  • 2011-05-25
  • 1970-01-01
  • 2010-12-22
  • 2020-02-06
  • 2021-10-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多