【问题标题】:Missing Custom Attriubutes缺少自定义属性
【发布时间】:2016-03-19 13:53:15
【问题描述】:

在 C# 中,可以使用反射通过m.CustomAttributes 获取成员m 的属性(请参阅the documentation for this property)。但是,这种方法似乎遗漏了Object 的GetType 方法上的三个自定义属性(参见the Object in the Reference Source for .NET Framework 4.6.1):

using System;
using System.Linq;
namespace ConsoleApplication1 {
  public class Program {
    public static void Main(string[] args) {
      var desiredCustomAttributes = typeof(object)
        .GetMethods()
        .First(m => m.Name == "GetType")
        .CustomAttributes
        .Select(ca => ca.ToString())
        .Where(s =>
          s.Contains("Pure") ||
          s.Contains("ResourceExposure") ||
          s.Contains("MethodImplAttribute"));
      var n = desiredCustomAttributes.Count();
      Console.WriteLine("Expected: 3");
      Console.WriteLine("  Actual: " + n); // prints "  Actual: 0"
      Console.ReadKey();
    }
  }
}

为什么这三个自定义属性不显示?

也许这与它是一个external 方法有关?

其实,身为外在与此无关。

using System;
using System.Linq;
using System.Runtime.Versioning;
namespace ConsoleApplication1 {
  public class ResourceExposureAttributeOnConstructor {
    [ResourceExposure(ResourceScope.None)]
    public ResourceExposureAttributeOnConstructor() { }
  }
  public class Program {
    public static void Main(string[] args) {
      var n = typeof(object)
        .GetConstructors()
        .First()
        .CustomAttributes
        .Select(ca => ca.ToString())
        .Where(s => s.Contains("ResourceExposure"))
        .Count();
      Console.WriteLine("Expected: 1");
      Console.WriteLine("  Actual: " + n); // prints "  Actual: 0"
      Console.ReadKey();
    }
  }
}

【问题讨论】:

    标签: c# .net reflection custom-attributes


    【解决方案1】:

    这不是因为方法是外部的。尝试使用用户定义的类:

    class MyAttr : Attribute { }
    class Program
    {
        [Pure]
        [ResourceExposure(ResourceScope.AppDomain)]
        [MethodImpl]
        [MyAttr]
        public void Foo() { }
    }
    

    .CustomAttributes 仅返回 MyAttr。我认为这仅仅是因为 FCL 不会将这三个属性作为自定义属性来威胁。查看源代码,MethodInfo.CustomAttributes 最终调用了MetadataImport.EnumCustomAttributes,其中调用了一个外部方法。

    [SecurityCritical]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private static extern void _Enum(IntPtr scope, int type, int parent, out MetadataEnumResult result);
    

    我没有调试它,但我认为这个方法知道一些内置属性并将它们从自定义属性中排除是有道理的。

    EDIT PureAttribute 和 ResourceExposureAttribute 是有条件构建的,这就是你无法获得它们的原因。

    [Conditional("RESOURCE_ANNOTATION_WORK")]
    public sealed class ResourceExposureAttribute : Attribute
    
    [Conditional("CONTRACTS_FULL")]
    public sealed class PureAttribute : Attribute
    

    看来MethodImplAttribute很特别。

    【讨论】:

    • “内置”属性是什么意思?从GetType 返回的一个自定义属性是__DynamicallyInvokable(参见this SE Q&A)。这个自定义属性显示在列表中但在源中 not 的事实表明它比其他三个更“内置”。
    • 所以假设实际行为是预期行为。那么如何知道调用CustomAttributes会返回哪些类型的自定义属性,哪些类型不会呢?
    • @TysonWilliams 我的意思是,custom attribute 的定义是由 FCL 制定的。显然用户定义的属性是自定义的。但不保证内置属性。
    • @TysonWilliams 恐怕你找不到自定义属性规则的官方列表。只是好奇,为什么你需要知道一个内置属性是否是自定义的?
    • 试图推断给定类型的依赖关系。 Object 显然依赖于这三个属性。有人编译了mscorelib,当然也包括Object。编译器需要知道Object 依赖于这三种类型。它是怎么做到的?
    猜你喜欢
    • 1970-01-01
    • 2019-03-04
    • 2019-12-11
    • 1970-01-01
    • 1970-01-01
    • 2021-04-25
    • 2018-07-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多