Skip to content

DynamicProxy does not support reference semantics with value types (C# 7.2) on .NET Core #339

Closed
@TAGC

Description

@TAGC

(Cross-posting some details from nsubstitute/NSubstitute#378)

C# 7.2 introduced the possibility of using reference semantics for value types - this is done by applying the in modifier for value-type parameters in method signatures.

Castle.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:

namespace SomeProject.Tests
{
    public readonly struct Struct
    {
    }

    public interface IStructByRefConsumer
    {
        void Consume(in Struct message);
    }

    public interface IStructByValueConsumer
    {
        void Consume(Struct message);
    }

    public class TempSpec
    {
        // Fails.
        [Fact]
        internal void Struct_ByRef_Moq_Test()
        {
            _ = Mock.Of<IStructByRefConsumer>();
        }

        // Fails.
        [Fact]
        internal void Struct_ByRef_NSubstitute_Test()
        {
            _ = Substitute.For<IStructByRefConsumer>();
        }

        // Passes.
        [Fact]
        internal void Struct_ByValue_Moq_Test()
        {
            _ = Mock.Of<IStructByValueConsumer>();
        }

        // Passes.
        [Fact]
        internal void Struct_ByValue_NSubstitute_Test()
        {
            _ = Substitute.For<IStructByValueConsumer>();
        }
    }
}

Posted below is the part of the stracktrace that's common between the failing Moq and NSubstitute tests:

Message: 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'.

Result StackTrace:	
at System.Reflection.Emit.TypeBuilder.TermCreateClass(RuntimeModule module, Int32 tk, ObjectHandleOnStack type)
   at System.Reflection.Emit.TypeBuilder.CreateTypeNoLock()
   at System.Reflection.Emit.TypeBuilder.CreateTypeInfo()
   at Castle.DynamicProxy.Generators.Emitters.AbstractTypeEmitter.CreateType(TypeBuilder type)
   at Castle.DynamicProxy.Generators.Emitters.AbstractTypeEmitter.BuildType()
   at Castle.DynamicProxy.Generators.InterfaceProxyWithoutTargetGenerator.GenerateType(String typeName, Type proxyTargetType, Type[] interfaces, INamingScope namingScope)
   at Castle.DynamicProxy.Generators.InterfaceProxyWithTargetGenerator.<>c__DisplayClass6_0.<GenerateCode>b__0(String n, INamingScope s)
   at Castle.DynamicProxy.Generators.BaseProxyGenerator.ObtainProxyType(CacheKey cacheKey, Func`3 factory)
   at Castle.DynamicProxy.ProxyGenerator.CreateInterfaceProxyWithoutTarget(Type interfaceToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, IInterceptor[] interceptors)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions