2015-12-14 4 views
1

En C#, on peut utiliser la réflexion pour obtenir les attributs sur un membre m via m.CustomAttributes (voir the documentation for this property). Cependant, cette approche semble manquer trois attributs personnalisés sur la méthode GetType de Object (voir the Object in the Reference Source for .NET Framework 4.6.1):Attriubutes personnalisées manquantes

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(); 
    } 
    } 
} 

Pourquoi ces trois attributs personnalisés montrent pas?

Peut-être qu'il a quelque chose à voir avec le fait qu'il est une méthode external?

En fait, être externe n'a rien à voir avec ça.

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(); 
    } 
    } 
} 

Répondre

1

Ce n'est pas parce que la méthode est externe. Essayé avec une classe définie par l'utilisateur:

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

.CustomAttributes retours MyAttr seulement. Je pense que c'est simplement parce que FCL ne menace pas les trois attributs en tant qu'attributs personnalisés. En regardant dans le code source, MethodInfo.CustomAttributes appelle finalement MetadataImport.EnumCustomAttributes, où une méthode externe est appelée.

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

Je ne l'ai pas déboguer en elle, mais je pense qu'il est logique que cette méthode connaît quelques attributs intégrés et les exclut des attributs personnalisés.

EDITPureAttribute et ResourceExposureAttribute sont conditionnellement construites, c'est la raison pour laquelle vous ne pouvez pas les obtenir.

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

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

Il semble que MethodImplAttribute est spécial.

+0

Qu'est-ce que cela signifie pour un attribut d'être "intégré"? Un attribut personnalisé renvoyé par 'GetType' est' __DynamicallyInvokable' (voir [ce SE Q & A] (http://stackoverflow.com/questions/12550749/what-is-the-dynamicallyinvokable-attribute-for)). Le fait que cet attribut personnalisé apparaisse dans la liste mais ne soit pas _ dans la source me suggère qu'il est plus "intégré" que ces trois autres. –

+0

Supposons donc que le comportement réel est le comportement attendu. Alors comment savoir quels types d'attributs personnalisés seront renvoyés d'un appel à 'CustomAttributes' et quels types ne le seront pas? –

+0

@TysonWilliams Je veux dire, la définition de 'custom attribute' est faite par FCL. Évidemment, les attributs définis par l'utilisateur sont personnalisés. Mais les attributs intégrés ne sont pas garantis. –