{"action":"created","issue":{"url":"https://api.github.com/repos/FakeItEasy/FakeItEasy/issues/144","repository_url":"https://api.github.com/repos/FakeItEasy/FakeItEasy","labels_url":"https://api.github.com/repos/FakeItEasy/FakeItEasy/issues/144/labels{/name}","comments_url":"https://api.github.com/repos/FakeItEasy/FakeItEasy/issues/144/comments","events_url":"https://api.github.com/repos/FakeItEasy/FakeItEasy/issues/144/events","html_url":"https://github.com/FakeItEasy/FakeItEasy/issues/144","id":16441679,"number":144,"title":"Allow IArgumentFormatter implementation to fall back on other formatters to render complex arguments","user":{"login":"blairconrad","id":3275797,"avatar_url":"https://avatars.githubusercontent.com/u/3275797?v=3","gravatar_id":"","url":"https://api.github.com/users/blairconrad","html_url":"https://github.com/blairconrad","followers_url":"https://api.github.com/users/blairconrad/followers","following_url":"https://api.github.com/users/blairconrad/following{/other_user}","gists_url":"https://api.github.com/users/blairconrad/gists{/gist_id}","starred_url":"https://api.github.com/users/blairconrad/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/blairconrad/subscriptions","organizations_url":"https://api.github.com/users/blairconrad/orgs","repos_url":"https://api.github.com/users/blairconrad/repos","events_url":"https://api.github.com/users/blairconrad/events{/privacy}","received_events_url":"https://api.github.com/users/blairconrad/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/FakeItEasy/FakeItEasy/labels/enhancement","name":"enhancement","color":"02e10c"},{"url":"https://api.github.com/repos/FakeItEasy/FakeItEasy/labels/P3","name":"P3","color":"a349a7"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":12,"created_at":"2013-07-07T11:01:06Z","updated_at":"2016-02-03T20:30:29Z","closed_at":null,"body":"Currently, FakeItEasy decides to invoke `IArgumentValueFormatter`s when there's unexpected or missing calls on a fake. This works pretty well.\r\n\r\nHowever, there's no way for FakeItEasy users to explicitly invoke the `FakeItEasy.Core.ArgumentValueFormatter` functionality  - the class is internal. The downside is that if users write their own formatter implementations, they have to specify every facet of how an object is rendered. There's no way to fall back to other formatters, unless the users have written these formatters themselves, or imported them from a library that exports them.\r\n\r\nSuppose there exists a class:\r\n\r\n```C#\r\nclass NamedValue\r\n{\r\n    public string Name;\r\n    public object Value;\r\n}\r\n```\r\n\r\nNot particularly inspiring, but someone may find it useful. Now suppose we want to write an argument value formatter for it. A naive implementation would be:\r\n\r\n```C#\r\nclass NameValueFormatter\r\n    : ArgumentValueFormatter<NamedValue>\r\n{\r\n    protected override string GetStringValue(NamedValue argumentValue)\r\n    {\r\n        return \"NamedValue{ Name=\" + argumentValue.Name + \r\n    \t     \", Value=\" + argumentValue.Value + \" }\";\r\n    }\r\n}\r\n```\r\nThis will give output like\r\n\r\n    NamedValue{ Name=temperature, Value=21.3 }\r\n\r\nNot bad. But suppose one of those values were `null`? Then we'd have\r\n\r\n    NamedValue{ Name=, Value=21.3 }\r\n\r\nA little disappointing. Maybe we'd rather see the `Name=<null>` kind of construction that the `ArgumentFormatter` would give if it were in charge or rendering `Name`.\r\n\r\nPerhaps worse, there's no way for you to tell that the `Value` that we rendered twice above is a string, not a float. If the `DefaultStringFormatter` had been invoked, we'd have seen \r\n\r\n    NamedValue{ Name=<null>, Value=\"21.3\" }\r\n\r\nOf course, existing formatters would have use when rendering more complicated types, such as those that contain collections, as well as the relatively simple kind of class I used above. (In fact, the very first time I tried to implement an `IArgumentValueFormatter`, I implemented a formatter for one custom type and then was dismayed to learn that not only was there no implicit leveraging of my formatter to format an array of the custom type, FakeItEasy provided me with no help. Of course in that case, I had access to the formatter for the custom type and I could use it, but it was a little awkward.)\r\n\r\nAnd if this issue is accepted, I'd be thrilled to work on it."},"comment":{"url":"https://api.github.com/repos/FakeItEasy/FakeItEasy/issues/comments/179446868","html_url":"https://github.com/FakeItEasy/FakeItEasy/issues/144#issuecomment-179446868","issue_url":"https://api.github.com/repos/FakeItEasy/FakeItEasy/issues/144","id":179446868,"user":{"login":"thomaslevesque","id":1864281,"avatar_url":"https://avatars.githubusercontent.com/u/1864281?v=3","gravatar_id":"","url":"https://api.github.com/users/thomaslevesque","html_url":"https://github.com/thomaslevesque","followers_url":"https://api.github.com/users/thomaslevesque/followers","following_url":"https://api.github.com/users/thomaslevesque/following{/other_user}","gists_url":"https://api.github.com/users/thomaslevesque/gists{/gist_id}","starred_url":"https://api.github.com/users/thomaslevesque/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/thomaslevesque/subscriptions","organizations_url":"https://api.github.com/users/thomaslevesque/orgs","repos_url":"https://api.github.com/users/thomaslevesque/repos","events_url":"https://api.github.com/users/thomaslevesque/events{/privacy}","received_events_url":"https://api.github.com/users/thomaslevesque/received_events","type":"User","site_admin":false},"created_at":"2016-02-03T20:30:29Z","updated_at":"2016-02-03T20:30:29Z","body":"Anyway, I'm curious to know how much real users care about this feature... I suspect that the vast majority never wrote an argument value formatter (I never did). If your test fails and the output isn't clear enough, well, you just put a breakpoint and look at the object yourself...\r\n\r\nSo perhaps a more useful improvement would be to provide a default formatter that writes the object with its property values, like the C# REPL does."}}