Closed abagonhishead closed 1 year ago
I should also have pointed out that this throws the same exception:
var proxy = new Castle.DynamicProxy.ProxyGenerator().CreateInterfaceProxyWithoutTarget(typeof(ITestInterface1));
So I'm guessing this is a DynamicProxy issue -- either that or both Moq and I are calling the wrong method.
This also affects classes: Example on dotnetfiddle
using System;
using Moq;
public class Program
{
public static void Main()
{
var mock1 = new Mock<TestClass1>();
var mock2 = new Mock<TestClass2>();
// Throws
var instance1 = mock1.Object;
// Does not throw
var instance2 = mock2.Object;
}
public class TestClass1
{
public virtual bool TestMethod<TEnum>(out TEnum? someValue)
where TEnum : Enum
{
someValue = default(TEnum?);
return false;
}
}
public class TestClass2
{
public virtual bool TestMethod<TEnum>(out TEnum? someValue)
{
someValue = default(TEnum?);
return false;
}
}
}
Stack trace:
Unhandled exception. System.ArgumentException: Cannot create an instance of TEnum because Type.ContainsGenericParameters is true.
at System.RuntimeType.CreateInstanceCheckThis()
at System.RuntimeType.ActivatorCache..ctor(RuntimeType rt)
at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean wrapExceptions)
at System.Activator.CreateInstance(Type type, Boolean nonPublic, Boolean wrapExceptions)
at System.Activator.CreateInstance(Type type)
at Castle.DynamicProxy.Generators.Emitters.OpCodeUtil.GetUnderlyingTypeOfEnum(Type enumType)
at Castle.DynamicProxy.Generators.Emitters.OpCodeUtil.EmitLoadIndirectOpCodeForType(ILGenerator gen, Type type)
at Castle.DynamicProxy.Generators.Emitters.SimpleAST.IndirectReference.LoadReference(ILGenerator gen)
at Castle.DynamicProxy.Generators.Emitters.SimpleAST.ReferencesToObjectArrayExpression.Emit(ILGenerator gen)
at Castle.DynamicProxy.Generators.Emitters.SimpleAST.NewInstanceExpression.Emit(ILGenerator gen)
at Castle.DynamicProxy.Generators.Emitters.SimpleAST.AssignStatement.Emit(ILGenerator gen)
at Castle.DynamicProxy.Generators.Emitters.CodeBuilder.Generate(ILGenerator il)
at Castle.DynamicProxy.Generators.Emitters.MethodEmitter.Generate()
at Castle.DynamicProxy.Generators.Emitters.AbstractTypeEmitter.EnsureBuildersAreInAValidState()
at Castle.DynamicProxy.Generators.Emitters.AbstractTypeEmitter.BuildType()
at Castle.DynamicProxy.Generators.BaseClassProxyGenerator.GenerateType(String name, INamingScope namingScope)
at Castle.DynamicProxy.Generators.BaseProxyGenerator.<>c__DisplayClass13_0.<GetProxyType>b__0(CacheKey cacheKey)
at Castle.Core.Internal.SynchronizedDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
at Castle.DynamicProxy.Generators.BaseProxyGenerator.GetProxyType()
at Castle.DynamicProxy.DefaultProxyBuilder.CreateClassProxyType(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options)
at Castle.DynamicProxy.ProxyGenerator.CreateClassProxyType(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options)
at Castle.DynamicProxy.ProxyGenerator.CreateClassProxy(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, Object[] constructorArguments, IInterceptor[] interceptors)
at Moq.CastleProxyFactory.CreateProxy(Type mockType, IInterceptor interceptor, Type[] interfaces, Object[] arguments) in /_/src/Moq/Interception/CastleProxyFactory.cs:line 110
at Moq.Mock`1.InitializeInstance() in /_/src/Moq/Mock`1.cs:line 502
at Moq.Mock`1.OnGetObject() in /_/src/Moq/Mock`1.cs:line 516
at Moq.Mock.get_Object() in /_/src/Moq/Mock.cs:line 180
at Moq.Mock`1.get_Object() in /_/src/Moq/Mock`1.cs:line 453
at Program.Main()
@abagonhishead, thanks for reporting, I'm going to take a look at it.
This is apparently caused by type checks inside OpCodeUtil.EmitLoadIndirectOpCodeForType
and OpCodeUtil.EmitStoreIndirectOpCodeForType
running in the wrong order: there is a check for type.IsEnum
which runs before type.IsGenericParameter
. If we switch the ordering of those type checks, the reported problem disappears.
Hi there, I encountered this using Moq but, from what I could see in the stack trace, it appears to be an issue with Castle.DynamicProxy. Hopefully raising this here is the correct thing to do. Let me know if I'm wrong and I can raise it with them instead!
I'm not familiar with DynamicProxy so hopefully it's easy enough to suss out.
This is on .NET 6, Moq version 4.20.69 which is using Castle.Core 5.1.1
Example reproduction using Moq on dotnetfiddle
Exception:
Stack trace: