{"action":"created","issue":{"url":"https://api.github.com/repos/dotnet/corefx/issues/6078","repository_url":"https://api.github.com/repos/dotnet/corefx","labels_url":"https://api.github.com/repos/dotnet/corefx/issues/6078/labels{/name}","comments_url":"https://api.github.com/repos/dotnet/corefx/issues/6078/comments","events_url":"https://api.github.com/repos/dotnet/corefx/issues/6078/events","html_url":"https://github.com/dotnet/corefx/issues/6078","id":133330339,"number":6078,"title":"CustomAttributeExtensions.GetCustomAttribute does not return inherited attributes for indexer argument","user":{"login":"drieseng","id":312863,"avatar_url":"https://avatars.githubusercontent.com/u/312863?v=3","gravatar_id":"","url":"https://api.github.com/users/drieseng","html_url":"https://github.com/drieseng","followers_url":"https://api.github.com/users/drieseng/followers","following_url":"https://api.github.com/users/drieseng/following{/other_user}","gists_url":"https://api.github.com/users/drieseng/gists{/gist_id}","starred_url":"https://api.github.com/users/drieseng/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/drieseng/subscriptions","organizations_url":"https://api.github.com/users/drieseng/orgs","repos_url":"https://api.github.com/users/drieseng/repos","events_url":"https://api.github.com/users/drieseng/events{/privacy}","received_events_url":"https://api.github.com/users/drieseng/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/dotnet/corefx/labels/System.Reflection","name":"System.Reflection","color":"d4c5f9"}],"state":"open","locked":false,"assignee":{"login":"AtsushiKan","id":13223578,"avatar_url":"https://avatars.githubusercontent.com/u/13223578?v=3","gravatar_id":"","url":"https://api.github.com/users/AtsushiKan","html_url":"https://github.com/AtsushiKan","followers_url":"https://api.github.com/users/AtsushiKan/followers","following_url":"https://api.github.com/users/AtsushiKan/following{/other_user}","gists_url":"https://api.github.com/users/AtsushiKan/gists{/gist_id}","starred_url":"https://api.github.com/users/AtsushiKan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/AtsushiKan/subscriptions","organizations_url":"https://api.github.com/users/AtsushiKan/orgs","repos_url":"https://api.github.com/users/AtsushiKan/repos","events_url":"https://api.github.com/users/AtsushiKan/events{/privacy}","received_events_url":"https://api.github.com/users/AtsushiKan/received_events","type":"User","site_admin":false},"milestone":{"url":"https://api.github.com/repos/dotnet/corefx/milestones/4","html_url":"https://github.com/dotnet/corefx/milestones/1.1.0","labels_url":"https://api.github.com/repos/dotnet/corefx/milestones/4/labels","id":1248719,"number":4,"title":"1.1.0","description":"Features associated with 1.1.0 unfortunately won't make it into the initial 1.0.0 RTM release.  We are tentatively planning on shipping them in the initial feature release after 1.0.0 RTM.\r\n\r\nNo calendar date is set.\r\n\r\nhttps://github.com/aspnet/Home/wiki/Roadmap","creator":{"login":"joshfree","id":1302850,"avatar_url":"https://avatars.githubusercontent.com/u/1302850?v=3","gravatar_id":"","url":"https://api.github.com/users/joshfree","html_url":"https://github.com/joshfree","followers_url":"https://api.github.com/users/joshfree/followers","following_url":"https://api.github.com/users/joshfree/following{/other_user}","gists_url":"https://api.github.com/users/joshfree/gists{/gist_id}","starred_url":"https://api.github.com/users/joshfree/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/joshfree/subscriptions","organizations_url":"https://api.github.com/users/joshfree/orgs","repos_url":"https://api.github.com/users/joshfree/repos","events_url":"https://api.github.com/users/joshfree/events{/privacy}","received_events_url":"https://api.github.com/users/joshfree/received_events","type":"User","site_admin":false},"open_issues":410,"closed_issues":757,"state":"open","created_at":"2015-08-10T18:04:00Z","updated_at":"2016-06-08T16:21:25Z","due_on":"2016-11-30T08:00:00Z","closed_at":null},"comments":1,"created_at":"2016-02-12T20:01:32Z","updated_at":"2016-06-08T16:33:25Z","closed_at":null,"body":"System.Reflection.CustomAttributeExtensions.GetCustomAttribute(this ParameterInfo element, Type attributeType, bool inherit) - which is located in the **System.Reflection.Extensions** assembly - does not returned inherited attributes for indexer arguments.\r\n\r\nIt does work fine for method arguments though (for example).\r\n\r\nTo reproduce, compile and run the following code snippet:\r\n\r\n```c#\r\nusing System;\r\nusing System.Reflection;\r\n\r\nnamespace ConsoleApp1\r\n{\r\n    public class Program\r\n    {\r\n        static void Main()\r\n        {\r\n            var indexerParam = typeof(Sub).GetProperty(\"Item\").GetIndexParameters()[0];\r\n\r\n            var indexerParamAttr = indexerParam.GetCustomAttribute(typeof(MyAttribute), true);\r\n            Console.WriteLine($\"Indexer: {indexerParamAttr != null}\");\r\n\r\n            var methodParam = typeof(Sub).GetMethod(\"Run\").GetParameters()[0];\r\n\r\n            var methodParamAttr = methodParam.GetCustomAttribute(typeof(MyAttribute), true);\r\n            Console.WriteLine($\"Method: {methodParamAttr != null}\");\r\n        }\r\n    }\r\n\r\n    [AttributeUsage(AttributeTargets.All)]\r\n    public class MyAttribute : Attribute\r\n    {\r\n\r\n    }\r\n\r\n    public abstract class Base\r\n    {\r\n        public abstract string Run([MyAttribute] int[] args);\r\n        public abstract object this[[MyAttribute] int[] args] { get; set; }\r\n    }\r\n\r\n    public class Sub : Base\r\n    {\r\n        public override string Run(int[] args)\r\n        {\r\n            return null;\r\n        }\r\n\r\n        public override object this[int[] args]\r\n        {\r\n            get { return null; }\r\n            set { }\r\n        }\r\n    }\r\n}\r\n```\r\n\r\nExpected result:\r\n\r\n```text\r\nIndexer: True\r\nMethod: True\r\n```\r\n\r\nActual result:\r\n\r\n```text\r\nIndexer: False\r\nMethod: True\r\n```"},"comment":{"url":"https://api.github.com/repos/dotnet/corefx/issues/comments/224648631","html_url":"https://github.com/dotnet/corefx/issues/6078#issuecomment-224648631","issue_url":"https://api.github.com/repos/dotnet/corefx/issues/6078","id":224648631,"user":{"login":"AtsushiKan","id":13223578,"avatar_url":"https://avatars.githubusercontent.com/u/13223578?v=3","gravatar_id":"","url":"https://api.github.com/users/AtsushiKan","html_url":"https://github.com/AtsushiKan","followers_url":"https://api.github.com/users/AtsushiKan/followers","following_url":"https://api.github.com/users/AtsushiKan/following{/other_user}","gists_url":"https://api.github.com/users/AtsushiKan/gists{/gist_id}","starred_url":"https://api.github.com/users/AtsushiKan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/AtsushiKan/subscriptions","organizations_url":"https://api.github.com/users/AtsushiKan/orgs","repos_url":"https://api.github.com/users/AtsushiKan/repos","events_url":"https://api.github.com/users/AtsushiKan/events{/privacy}","received_events_url":"https://api.github.com/users/AtsushiKan/received_events","type":"User","site_admin":false},"created_at":"2016-06-08T16:33:25Z","updated_at":"2016-06-08T16:33:25Z","body":"cc @weshaggard \r\ncc @nguerrera \r\ncc @mellinoe \r\n\r\nGuys, what are your thoughts on this?\r\n\r\n\r\n<b>Issue</b>\r\n\r\nParameterInfo objects returned by callling <b>PropertyInfo.GetIndexParameters()</b> are reported as not seeing inherited custom attributes.\r\n\r\n<b>How to fix this</b>\r\nDefining what custom attributes are attached or even what inheritance means is dodgy because at the metadata level, properties do not have parameters. Only their getter/setter methods do. (And in theory, the getter and setter methods could attach different custom attributes to their parameters, and have different inheritance chains.)\r\n\r\nPropertyInfo.GetIndexParameters() works by looking for a getter method - if none exists, then a setter method. It captures the parameter list of the chosen accessor method, wraps them in a secondary ParameterInfo object that behaves identically to the method version <i>except</i> that the Member property returns a PropertyInfo rather than a MethodInfo. In other worse, this ParameterInfo is a bit of a lie.\r\n\r\nThe desktop/NETCore implementation does copy the original parameter's metadata token over. This allows GetCustomAttributes to \"work\" for directly defined attributes (provided you're not worried about the freak case where the getter and setter define different custom attributes.) Which is in a way unfortunate, because if we hadn't done this, it would make it easier to justify not adding support for inherited custom attributes.\r\n\r\nGetCustomAttributes does not find inherited attributes as the code only scans up the chain if the ParameterInfo.Member property returns a MethodInfo. Otherwise, it assumes without checking that the member is a ConstructorInfo, which can never be \"inherited.\" The third possibility - PropertyInfo was probably overlooked.\r\n\r\nThe most consistent way to \"fix\" the current behavior would probably be:\r\n\r\n- Remember if the ParameterInfo wraps the getter or the setter.\r\n- Treat a query for custom attributes on the ParameterInfo as if it were a query for custom attributes\r\n  on the original getter/setter ParameterInfo.\r\n\r\n<b>Bottom Line</b>\r\n\r\nI see this a cost-benefit decision. I'm leaning against fixing this but it's worth throwing up for api discussion.\r\n\r\n<b>Pros of fixing:</b>\r\n\r\nReturning directly defined custom attributes but disregarding the \"inherited\" flag breaks the principle of least surprise. \r\n\r\n\r\n<b>Cons of fixing:</b>\r\n\r\nThis would be a potentially breaking change for the full framework (from 3.5 onward). It would also have to be fixed independently in the .Net Native implementation as we emulated the desktop behavior over there.\r\n\r\nThis is easy to work around: use the PropertyInfo from the actual getter/setter method.\r\n\r\nThis doubles down on the questionable decision of exposing a \"property parameter\" through Reflection in the first place. Such a thing simply doesn't reflect the underlying metadata model.\r\n\r\n\r\n\r\n"}}
{"actor":{"display_login":"AtsushiKan"}}