{"action":"created","issue":{"url":"https://api.github.com/repos/castleproject/Core/issues/339","repository_url":"https://api.github.com/repos/castleproject/Core","labels_url":"https://api.github.com/repos/castleproject/Core/issues/339/labels{/name}","comments_url":"https://api.github.com/repos/castleproject/Core/issues/339/comments","events_url":"https://api.github.com/repos/castleproject/Core/issues/339/events","html_url":"https://github.com/castleproject/Core/issues/339","id":304443306,"number":339,"title":"DynamicProxy does not support reference semantics with value types (C# 7.2)","user":{"login":"TAGC","id":1588951,"avatar_url":"https://avatars2.githubusercontent.com/u/1588951?v=4","gravatar_id":"","url":"https://api.github.com/users/TAGC","html_url":"https://github.com/TAGC","followers_url":"https://api.github.com/users/TAGC/followers","following_url":"https://api.github.com/users/TAGC/following{/other_user}","gists_url":"https://api.github.com/users/TAGC/gists{/gist_id}","starred_url":"https://api.github.com/users/TAGC/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/TAGC/subscriptions","organizations_url":"https://api.github.com/users/TAGC/orgs","repos_url":"https://api.github.com/users/TAGC/repos","events_url":"https://api.github.com/users/TAGC/events{/privacy}","received_events_url":"https://api.github.com/users/TAGC/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":10,"created_at":"2018-03-12T16:24:19Z","updated_at":"2018-03-13T16:32:35Z","closed_at":null,"author_association":"NONE","body":"(Cross-posting some details from nsubstitute/NSubstitute#378)\r\n\r\nC# 7.2 introduced [the possibility of using reference semantics for value types](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-7-2#reference-semantics-with-value-types) - this is done by applying the `in` modifier for value-type parameters in method signatures.\r\n\r\nCastle.Core does not seem to support generating mocks for interfaces that use `in` modifiers for value types. This has been reproduced using Castle.Core indirectly through the latest stable versions of Moq and NSubstitute:\r\n\r\n```cs\r\nnamespace SomeProject.Tests\r\n{\r\n    public readonly struct Struct\r\n    {\r\n    }\r\n\r\n    public interface IStructByRefConsumer\r\n    {\r\n        void Consume(in Struct message);\r\n    }\r\n\r\n    public interface IStructByValueConsumer\r\n    {\r\n        void Consume(Struct message);\r\n    }\r\n\r\n    public class TempSpec\r\n    {\r\n        // Fails.\r\n        [Fact]\r\n        internal void Struct_ByRef_Moq_Test()\r\n        {\r\n            _ = Mock.Of<IStructByRefConsumer>();\r\n        }\r\n\r\n        // Fails.\r\n        [Fact]\r\n        internal void Struct_ByRef_NSubstitute_Test()\r\n        {\r\n            _ = Substitute.For<IStructByRefConsumer>();\r\n        }\r\n\r\n        // Passes.\r\n        [Fact]\r\n        internal void Struct_ByValue_Moq_Test()\r\n        {\r\n            _ = Mock.Of<IStructByValueConsumer>();\r\n        }\r\n\r\n        // Passes.\r\n        [Fact]\r\n        internal void Struct_ByValue_NSubstitute_Test()\r\n        {\r\n            _ = Substitute.For<IStructByValueConsumer>();\r\n        }\r\n    }\r\n}\r\n```\r\n\r\nPosted below is the part of the stracktrace that's common between the failing Moq and NSubstitute tests:\r\n\r\n```\r\nMessage: System.TypeLoadException : Signature of the body and declaration in a method implementation do not match.  Type: 'Castle.Proxies.IStructByRefConsumerProxy'.  Assembly: 'DynamicProxyGenAssembly2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.\r\n\r\nResult StackTrace:\t\r\nat System.Reflection.Emit.TypeBuilder.TermCreateClass(RuntimeModule module, Int32 tk, ObjectHandleOnStack type)\r\n   at System.Reflection.Emit.TypeBuilder.CreateTypeNoLock()\r\n   at System.Reflection.Emit.TypeBuilder.CreateTypeInfo()\r\n   at Castle.DynamicProxy.Generators.Emitters.AbstractTypeEmitter.CreateType(TypeBuilder type)\r\n   at Castle.DynamicProxy.Generators.Emitters.AbstractTypeEmitter.BuildType()\r\n   at Castle.DynamicProxy.Generators.InterfaceProxyWithoutTargetGenerator.GenerateType(String typeName, Type proxyTargetType, Type[] interfaces, INamingScope namingScope)\r\n   at Castle.DynamicProxy.Generators.InterfaceProxyWithTargetGenerator.<>c__DisplayClass6_0.<GenerateCode>b__0(String n, INamingScope s)\r\n   at Castle.DynamicProxy.Generators.BaseProxyGenerator.ObtainProxyType(CacheKey cacheKey, Func`3 factory)\r\n   at Castle.DynamicProxy.ProxyGenerator.CreateInterfaceProxyWithoutTarget(Type interfaceToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, IInterceptor[] interceptors)\r\n```"},"comment":{"url":"https://api.github.com/repos/castleproject/Core/issues/comments/372730258","html_url":"https://github.com/castleproject/Core/issues/339#issuecomment-372730258","issue_url":"https://api.github.com/repos/castleproject/Core/issues/339","id":372730258,"user":{"login":"thomaslevesque","id":1864281,"avatar_url":"https://avatars3.githubusercontent.com/u/1864281?v=4","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":"2018-03-13T16:32:35Z","updated_at":"2018-03-13T16:32:35Z","author_association":"CONTRIBUTOR","body":"> I guess its time to also add a .NET Standard 2.0 build\r\n\r\nWhy 2.0? If the necessary APIs are supported in 1.5, why not target the lowest possible version to support the largest number of consumers? Is there a compelling reason to target 2.0?\r\n\r\nWe [considered](https://github.com/FakeItEasy/FakeItEasy/issues/1186) releasing a netstandard2.0 version of FakeItEasy in order to support binary serialization (which is disabled in netstandard1.3 builds), but \r\n\r\n> .NET 4.6.1 probably prefers the .NET Standard 1.3 build to the .NET Framework builds (a problem that has cropped up since .NET 4.6.1 was retroactively changed to support .NET standard 2.0), explaining why it is affected by this as well.\r\n\r\nI don't think that's the reason; I just tried it, making sure to reference the net45 version of Castle.Core, and the problem with the generic interface still occurs. I think this is a related but different bug."}}
{"actor":{"display_login":"thomaslevesque"}}