una ponen etiquetas estandar documentar documentacion descargar crear como comentarios codigo clases clase c# .net reflection custom-attributes bcl

c# - ponen - La reflexión con la sintaxis genérica falla en un parámetro de retorno de un método invalidado



estandar de documentacion de codigo c# (1)

Para evitar la sintaxis no genérica pasada de moda cuando se buscan atributos de un tipo conocido, uno usualmente usa los métodos de extensión en la clase System.Reflection.CustomAttributeExtensions (desde .NET 4.5).

Sin embargo, esto parece fallar si busca un atributo en el parámetro de retorno de un método invalidado (o un elemento de acceso de una propiedad / indexador anulado).

Estoy experimentando esto con .NET 4.6.1.

Reproducción simple (completa):

using System; using System.Reflection; namespace ReflectionTrouble { class B { //[return: MyMark("In base class")] // uncommenting does not help public virtual int M() => 0; } class C : B { [return: MyMark("In inheriting class")] // commenting away attribute does not help public override int M() => -1; } [AttributeUsage(AttributeTargets.ReturnValue, AllowMultiple = false, Inherited = false)] // commenting away AttributeUsage does not help sealed class MyMarkAttribute : Attribute { public string Descr { get; } public MyMarkAttribute(string descr) { Descr = descr; } public override string ToString() => $"MyMark({Descr})"; } static class Program { static void Main() { var derivedReturnVal = typeof(C).GetMethod("M").ReturnParameter; // usual new generic syntax (extension method in System.Refelction namespace): var attr = derivedReturnVal.GetCustomAttribute<MyMarkAttribute>(); // BLOWS UP HERE, System.IndexOutOfRangeException: Index was outside the bounds of the array. Console.WriteLine(attr); // old non-generic syntax without extension method works: var attr2 = ((MyMarkAttribute[])(derivedReturnVal.GetCustomAttributes(typeof(MyMarkAttribute), false)))[0]; // OK Console.WriteLine(attr2); } } }

El código puede parecer "demasiado largo para leer", pero en realidad es solo un método anulado con un atributo en su parámetro de retorno y el intento obvio de recuperar esa instancia de atributo.

Traza de pila

Unhandled Exception: System.IndexOutOfRangeException: Index was outside the bounds of the array. at System.Attribute.GetParentDefinition(ParameterInfo param) at System.Attribute.InternalParamGetCustomAttributes(ParameterInfo param, Type type, Boolean inherit) at System.Attribute.GetCustomAttributes(ParameterInfo element, Type attributeType, Boolean inherit) at System.Attribute.GetCustomAttribute(ParameterInfo element, Type attributeType, Boolean inherit) at System.Reflection.CustomAttributeExtensions.GetCustomAttribute[T](ParameterInfo element) at ReflectionTrouble.Program.Main() in c:/MyPath/Program.cs:line 38

¿Estoy haciendo algo obviamente mal?

¿Es esto un error, y si es así, es bien conocido, y es un error viejo?


Esto de hecho parece un error. El problema parece estar con la herencia. Esto funciona:

ReturnParameter.GetCustomAttribute<MyMark>(inherit: false)

Los atributos de recuperación tienen dos rutas de código que funcionan de manera un poco diferente: MemberInfo.GetCustomAttribute (más antiguo) y Attribute.GetCustomAttribute (más reciente y recomendada). También existen los métodos de extensión genéricos, que utilizan este último enfoque, más reciente. La diferencia entre estos es, de hecho, la forma en que manejan la herencia. .NET 1.0 ignoró el parámetro inherit para propiedades, eventos y parámetros. Entonces, para no romper las cosas, los métodos estáticos en el Attribute que introdujimos en .NET 2.0 (junto con este error).

Parece que descuidaron el caso del parámetro de valor de retorno al subir el árbol de herencia (ver here ). Puede abrir un problema en el repositorio de GitHub o en un error de conexión.