From 7c6730138353308f5cb7e3de88d8fc10bfc31652 Mon Sep 17 00:00:00 2001 From: stakx Date: Sun, 4 Aug 2019 21:24:21 +0200 Subject: [PATCH 1/9] Test failure due to type parameter name mismatch --- .../GenericMethodsProxyTestCase.cs | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/Castle.Core.Tests/DynamicProxy.Tests/GenericMethodsProxyTestCase.cs b/src/Castle.Core.Tests/DynamicProxy.Tests/GenericMethodsProxyTestCase.cs index 579b6be240..b9387ffd75 100644 --- a/src/Castle.Core.Tests/DynamicProxy.Tests/GenericMethodsProxyTestCase.cs +++ b/src/Castle.Core.Tests/DynamicProxy.Tests/GenericMethodsProxyTestCase.cs @@ -92,5 +92,32 @@ public void ProxyInterfaceWithGenericMethodWithTwoGenericParametersWhereOneIsBas { generator.CreateInterfaceProxyWithoutTarget(); } + + [Test] + [TestCase(typeof(Test))] + [TestCase(typeof(TestVirtual))] + public void GenericMethodDifferentlyNamedGenericArguments(Type classType) + { + generator.CreateClassProxy(classType, new[] { typeof(ITest) }); + } + + public interface ITest + { + void Hi(); + } + + public class Test : ITest + { + public void Hi() + { + } + } + + public class TestVirtual : ITest + { + public virtual void Hi() + { + } + } } } \ No newline at end of file From baf4ffb2d7b7d529bc063ea1f31d253ebb61e928 Mon Sep 17 00:00:00 2001 From: Dominique Schuppli Date: Mon, 22 Feb 2021 18:37:16 +0100 Subject: [PATCH 2/9] Make `GetClosedParameterType` an instance method --- .../Emitters/AbstractTypeEmitter.cs | 54 +++++++++++++++++++ .../DynamicProxy/Internal/TypeUtil.cs | 53 ------------------ 2 files changed, 54 insertions(+), 53 deletions(-) diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/AbstractTypeEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/AbstractTypeEmitter.cs index d2f41e39c2..a4ddcebc4f 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/AbstractTypeEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/AbstractTypeEmitter.cs @@ -266,6 +266,60 @@ public FieldReference GetField(string name) return value; } + public Type GetClosedParameterType(Type parameter) + { + if (parameter.IsGenericTypeDefinition) + { + return parameter.GetGenericTypeDefinition().MakeGenericType(GetGenericArgumentsFor(parameter)); + } + + if (parameter.IsGenericType) + { + var arguments = parameter.GetGenericArguments(); + if (CloseGenericParametersIfAny(arguments)) + { + return parameter.GetGenericTypeDefinition().MakeGenericType(arguments); + } + } + + if (parameter.IsGenericParameter) + { + return GetGenericArgument(parameter.Name); + } + + if (parameter.IsArray) + { + var elementType = GetClosedParameterType(parameter.GetElementType()); + int rank = parameter.GetArrayRank(); + return rank == 1 + ? elementType.MakeArrayType() + : elementType.MakeArrayType(rank); + } + + if (parameter.IsByRef) + { + var elementType = GetClosedParameterType(parameter.GetElementType()); + return elementType.MakeByRefType(); + } + + return parameter; + + bool CloseGenericParametersIfAny(Type[] arguments) + { + var hasAnyGenericParameters = false; + for (var i = 0; i < arguments.Length; i++) + { + var newType = GetClosedParameterType(arguments[i]); + if (newType != null && !ReferenceEquals(newType, arguments[i])) + { + arguments[i] = newType; + hasAnyGenericParameters = true; + } + } + return hasAnyGenericParameters; + } + } + public Type GetGenericArgument(string genericArgumentName) { if (name2GenericType.TryGetValue(genericArgumentName, out var genericTypeParameterBuilder)) diff --git a/src/Castle.Core/DynamicProxy/Internal/TypeUtil.cs b/src/Castle.Core/DynamicProxy/Internal/TypeUtil.cs index 9e757155b3..63a1f2d31d 100644 --- a/src/Castle.Core/DynamicProxy/Internal/TypeUtil.cs +++ b/src/Castle.Core/DynamicProxy/Internal/TypeUtil.cs @@ -98,44 +98,6 @@ public static Type[] GetAllInterfaces(this Type type) // NOTE: also used by Win return GetAllInterfaces(new[] { type }); } - internal static Type GetClosedParameterType(this AbstractTypeEmitter type, Type parameter) - { - if (parameter.IsGenericTypeDefinition) - { - return parameter.GetGenericTypeDefinition().MakeGenericType(type.GetGenericArgumentsFor(parameter)); - } - - if (parameter.IsGenericType) - { - var arguments = parameter.GetGenericArguments(); - if (CloseGenericParametersIfAny(type, arguments)) - { - return parameter.GetGenericTypeDefinition().MakeGenericType(arguments); - } - } - - if (parameter.IsGenericParameter) - { - return type.GetGenericArgument(parameter.Name); - } - - if (parameter.IsArray) - { - var elementType = GetClosedParameterType(type, parameter.GetElementType()); - int rank = parameter.GetArrayRank(); - return rank == 1 - ? elementType.MakeArrayType() - : elementType.MakeArrayType(rank); - } - - if (parameter.IsByRef) - { - var elementType = GetClosedParameterType(type, parameter.GetElementType()); - return elementType.MakeByRefType(); - } - - return parameter; - } public static Type GetTypeOrNull(object target) { @@ -232,21 +194,6 @@ internal static bool IsDelegateType(this Type type) return type.BaseType == typeof(MulticastDelegate); } - private static bool CloseGenericParametersIfAny(AbstractTypeEmitter emitter, Type[] arguments) - { - var hasAnyGenericParameters = false; - for (var i = 0; i < arguments.Length; i++) - { - var newType = GetClosedParameterType(emitter, arguments[i]); - if (newType != null && !ReferenceEquals(newType, arguments[i])) - { - arguments[i] = newType; - hasAnyGenericParameters = true; - } - } - return hasAnyGenericParameters; - } - private static Type[] Sort(ICollection types) { var array = new Type[types.Count]; From a917267a7d0d7614c4f29f5767143f6aba4c0113 Mon Sep 17 00:00:00 2001 From: Dominique Schuppli Date: Mon, 22 Feb 2021 18:41:23 +0100 Subject: [PATCH 3/9] Remove unreachable `GetGenericArgumentsFor` method --- .../Emitters/AbstractTypeEmitter.cs | 29 ++++--------------- 1 file changed, 5 insertions(+), 24 deletions(-) diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/AbstractTypeEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/AbstractTypeEmitter.cs index a4ddcebc4f..91a3ab1239 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/AbstractTypeEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/AbstractTypeEmitter.cs @@ -268,13 +268,13 @@ public FieldReference GetField(string name) public Type GetClosedParameterType(Type parameter) { - if (parameter.IsGenericTypeDefinition) - { - return parameter.GetGenericTypeDefinition().MakeGenericType(GetGenericArgumentsFor(parameter)); - } - if (parameter.IsGenericType) { + // ECMA-335 section II.9.4: "The CLI does not support partial instantiation + // of generic types. And generic types shall not appear uninstantiated any- + // where in metadata signature blobs." (And parameters are defined there!) + Debug.Assert(parameter.IsGenericTypeDefinition == false); + var arguments = parameter.GetGenericArguments(); if (CloseGenericParametersIfAny(arguments)) { @@ -328,25 +328,6 @@ public Type GetGenericArgument(string genericArgumentName) return null; } - public Type[] GetGenericArgumentsFor(Type genericType) - { - var types = new List(); - - foreach (var genType in genericType.GetGenericArguments()) - { - if (genType.IsGenericParameter) - { - types.Add(name2GenericType[genType.Name]); - } - else - { - types.Add(genType); - } - } - - return types.ToArray(); - } - public Type[] GetGenericArgumentsFor(MethodInfo genericMethod) { var types = new List(); From 5ee8335cf283e869df36e26e80abdc1266d4b34a Mon Sep 17 00:00:00 2001 From: Dominique Schuppli Date: Mon, 22 Feb 2021 18:48:21 +0100 Subject: [PATCH 4/9] Match generic parameters by position, not by name To understand why this change is permissible, it is helpful to know the types generated by DynamicProxy: * Proxy types. Those are (at present) never generic. * Delegate types and invocation classes. Those may be generic, and when they are, their generic parameters correspond exactly with those of some target method. It is this correspondence which makes any mapping by name unnecessary. --- .../Generators/Emitters/AbstractTypeEmitter.cs | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/AbstractTypeEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/AbstractTypeEmitter.cs index 91a3ab1239..02f031b47e 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/AbstractTypeEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/AbstractTypeEmitter.cs @@ -284,7 +284,7 @@ public Type GetClosedParameterType(Type parameter) if (parameter.IsGenericParameter) { - return GetGenericArgument(parameter.Name); + return GetGenericArgument(parameter.GenericParameterPosition); } if (parameter.IsArray) @@ -320,23 +320,18 @@ bool CloseGenericParametersIfAny(Type[] arguments) } } - public Type GetGenericArgument(string genericArgumentName) + public Type GetGenericArgument(int position) { - if (name2GenericType.TryGetValue(genericArgumentName, out var genericTypeParameterBuilder)) - return genericTypeParameterBuilder; + Debug.Assert(0 <= position && position < genericTypeParams.Length); - return null; + return genericTypeParams[position]; } public Type[] GetGenericArgumentsFor(MethodInfo genericMethod) { - var types = new List(); - foreach (var genType in genericMethod.GetGenericArguments()) - { - types.Add(name2GenericType[genType.Name]); - } + Debug.Assert(genericMethod.GetGenericArguments().Length == genericTypeParams.Length); - return types.ToArray(); + return genericTypeParams; } public void SetGenericTypeParameters(GenericTypeParameterBuilder[] genericTypeParameterBuilders) From 0789e880bf4a9eab4d7d1fc3fda602da61fccc18 Mon Sep 17 00:00:00 2001 From: Dominique Schuppli Date: Mon, 22 Feb 2021 19:01:13 +0100 Subject: [PATCH 5/9] Remove `name2GenericType` from `AbstractTypeEmitter` --- .../Generators/Emitters/AbstractTypeEmitter.cs | 4 +--- .../DynamicProxy/Generators/Emitters/GenericUtil.cs | 8 +++----- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/AbstractTypeEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/AbstractTypeEmitter.cs index 02f031b47e..43b7958186 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/AbstractTypeEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/AbstractTypeEmitter.cs @@ -36,7 +36,6 @@ internal abstract class AbstractTypeEmitter private readonly List methods; - private readonly Dictionary name2GenericType; private readonly List nested; private readonly List properties; private readonly TypeBuilder typebuilder; @@ -51,7 +50,6 @@ protected AbstractTypeEmitter(TypeBuilder typeBuilder) constructors = new List(); properties = new List(); events = new List(); - name2GenericType = new Dictionary(); } public Type BaseType @@ -113,7 +111,7 @@ public void CopyGenericParametersFromMethod(MethodInfo methodToCopyGenericsFrom) throw new InvalidOperationException("Cannot invoke me twice"); } - SetGenericTypeParameters(GenericUtil.CopyGenericArguments(methodToCopyGenericsFrom, typebuilder, name2GenericType)); + SetGenericTypeParameters(GenericUtil.CopyGenericArguments(methodToCopyGenericsFrom, typebuilder)); } public ConstructorEmitter CreateConstructor(params ArgumentReference[] arguments) diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/GenericUtil.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/GenericUtil.cs index 0447dc7533..feb746d9d9 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/GenericUtil.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/GenericUtil.cs @@ -29,12 +29,10 @@ internal class GenericUtil { public static GenericTypeParameterBuilder[] CopyGenericArguments( MethodInfo methodToCopyGenericsFrom, - TypeBuilder builder, - Dictionary name2GenericType) + TypeBuilder builder) { - return - CopyGenericArguments(methodToCopyGenericsFrom, name2GenericType, - builder.DefineGenericParameters); + var _ = new Dictionary(); + return CopyGenericArguments(methodToCopyGenericsFrom, _, builder.DefineGenericParameters); } public static GenericTypeParameterBuilder[] CopyGenericArguments( From cf4ad36b33292f9384b744a269e8d63a358713f2 Mon Sep 17 00:00:00 2001 From: Dominique Schuppli Date: Mon, 22 Feb 2021 19:39:21 +0100 Subject: [PATCH 6/9] `MethodEmitter` doesn't need `name2GenericType` The constructor being changed is only called by event/property emitters, via the `MetaType` model, and by contributors, all of which are used for proxy type generation only (and those are never generic). The only generic types generated by DynamicProxy are delegate types and invocation classes, but their generators never call this `MethodEmitter` ctor. --- .../Generators/Emitters/GenericUtil.cs | 15 --------------- .../Generators/Emitters/MethodEmitter.cs | 7 ++++++- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/GenericUtil.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/GenericUtil.cs index feb746d9d9..7cb3a33f81 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/GenericUtil.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/GenericUtil.cs @@ -103,21 +103,6 @@ public static Type[] ExtractParametersTypes( return newParameters; } - public static Dictionary GetGenericArgumentsMap(AbstractTypeEmitter parentEmitter) - { - if (parentEmitter.GenericTypeParams == null || parentEmitter.GenericTypeParams.Length == 0) - { - return new Dictionary(0); - } - - var name2GenericType = new Dictionary(parentEmitter.GenericTypeParams.Length); - foreach (var genType in parentEmitter.GenericTypeParams) - { - name2GenericType.Add(genType.Name, genType); - } - return name2GenericType; - } - private static Type AdjustConstraintToNewGenericParameters( Type constraint, MethodInfo methodToCopyGenericsFrom, Type[] originalGenericParameters, GenericTypeParameterBuilder[] newGenericParameters) diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/MethodEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/MethodEmitter.cs index 3d51910c36..629f6bdd28 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/MethodEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/MethodEmitter.cs @@ -15,6 +15,7 @@ namespace Castle.DynamicProxy.Generators.Emitters { using System; + using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; @@ -57,7 +58,11 @@ internal MethodEmitter(AbstractTypeEmitter owner, string name, MethodAttributes attributes, MethodInfo methodToUseAsATemplate) : this(owner, name, attributes) { - var name2GenericType = GenericUtil.GetGenericArgumentsMap(owner); + // All code paths leading up to this constructor can be traced back to + // proxy type generation code. At present, proxy types are never generic. + Debug.Assert(owner.GenericTypeParams == null || owner.GenericTypeParams.Length == 0); + + var name2GenericType = new Dictionary(0); var returnType = GenericUtil.ExtractCorrectType(methodToUseAsATemplate.ReturnType, name2GenericType); var baseMethodParameters = methodToUseAsATemplate.GetParameters(); From c90b6afe0d3aa49d925676122bc9ed1015105468 Mon Sep 17 00:00:00 2001 From: Dominique Schuppli Date: Mon, 22 Feb 2021 19:50:18 +0100 Subject: [PATCH 7/9] Remove `name2GenericType` from `MethodEmitter` Because `name2GenericType` is in practice always an empty dictionary, the helper methods `ExtractCorrectType` and `ExtractParametersTypes` in `GenericUtil` don't really do anything. They can be removed since noone else is using them. (Side note: it looks like `ExtractCorrectType` might have malfunctioned, had it ever actually done anything: it maps parameters `T` -> `Tmapped` and arrays `T[]` -> `Tmapped[]`, but forgets about instantiatd generic types involving `T` as an argument, such as `IEnumerable`.) --- .../Generators/Emitters/GenericUtil.cs | 66 +------------------ .../Generators/Emitters/MethodEmitter.cs | 8 +-- 2 files changed, 6 insertions(+), 68 deletions(-) diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/GenericUtil.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/GenericUtil.cs index 7cb3a33f81..762483c27a 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/GenericUtil.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/GenericUtil.cs @@ -37,70 +37,10 @@ public static GenericTypeParameterBuilder[] CopyGenericArguments( public static GenericTypeParameterBuilder[] CopyGenericArguments( MethodInfo methodToCopyGenericsFrom, - MethodBuilder builder, - Dictionary name2GenericType) + MethodBuilder builder) { - return - CopyGenericArguments(methodToCopyGenericsFrom, name2GenericType, - builder.DefineGenericParameters); - } - - public static Type ExtractCorrectType(Type paramType, Dictionary name2GenericType) - { - if (paramType.IsArray) - { - var rank = paramType.GetArrayRank(); - - var underlyingType = paramType.GetElementType(); - - if (underlyingType.IsGenericParameter) - { - GenericTypeParameterBuilder genericType; - if (name2GenericType.TryGetValue(underlyingType.Name, out genericType) == false) - { - return paramType; - } - - if (rank == 1) - { - return genericType.MakeArrayType(); - } - return genericType.MakeArrayType(rank); - } - if (rank == 1) - { - return underlyingType.MakeArrayType(); - } - return underlyingType.MakeArrayType(rank); - } - - if (paramType.IsGenericParameter) - { - GenericTypeParameterBuilder value; - if (name2GenericType.TryGetValue(paramType.Name, out value)) - { - return value; - } - } - - return paramType; - } - - public static Type[] ExtractParametersTypes( - ParameterInfo[] baseMethodParameters, - Dictionary name2GenericType) - { - var newParameters = new Type[baseMethodParameters.Length]; - - for (var i = 0; i < baseMethodParameters.Length; i++) - { - var param = baseMethodParameters[i]; - var paramType = param.ParameterType; - - newParameters[i] = ExtractCorrectType(paramType, name2GenericType); - } - - return newParameters; + var _ = new Dictionary(); + return CopyGenericArguments(methodToCopyGenericsFrom, _, builder.DefineGenericParameters); } private static Type AdjustConstraintToNewGenericParameters( diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/MethodEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/MethodEmitter.cs index 629f6bdd28..7d2579f10f 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/MethodEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/MethodEmitter.cs @@ -62,13 +62,11 @@ internal MethodEmitter(AbstractTypeEmitter owner, string name, // proxy type generation code. At present, proxy types are never generic. Debug.Assert(owner.GenericTypeParams == null || owner.GenericTypeParams.Length == 0); - var name2GenericType = new Dictionary(0); - - var returnType = GenericUtil.ExtractCorrectType(methodToUseAsATemplate.ReturnType, name2GenericType); + var returnType = methodToUseAsATemplate.ReturnType; var baseMethodParameters = methodToUseAsATemplate.GetParameters(); - var parameters = GenericUtil.ExtractParametersTypes(baseMethodParameters, name2GenericType); + var parameters = ArgumentsUtil.GetTypes(baseMethodParameters); - genericTypeParams = GenericUtil.CopyGenericArguments(methodToUseAsATemplate, builder, name2GenericType); + genericTypeParams = GenericUtil.CopyGenericArguments(methodToUseAsATemplate, builder); SetParameters(parameters); SetReturnType(returnType); SetSignature(returnType, methodToUseAsATemplate.ReturnParameter, parameters, baseMethodParameters); From 25884c032570069275d9110037a690d400e05f01 Mon Sep 17 00:00:00 2001 From: Dominique Schuppli Date: Mon, 22 Feb 2021 20:02:04 +0100 Subject: [PATCH 8/9] Remove `name2GenericType` from `GenericUtil` --- .../DynamicProxy/Generators/Emitters/GenericUtil.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/GenericUtil.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/GenericUtil.cs index 762483c27a..458ce775a8 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/GenericUtil.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/GenericUtil.cs @@ -15,7 +15,6 @@ namespace Castle.DynamicProxy.Generators.Emitters { using System; - using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Reflection.Emit; @@ -31,16 +30,14 @@ public static GenericTypeParameterBuilder[] CopyGenericArguments( MethodInfo methodToCopyGenericsFrom, TypeBuilder builder) { - var _ = new Dictionary(); - return CopyGenericArguments(methodToCopyGenericsFrom, _, builder.DefineGenericParameters); + return CopyGenericArguments(methodToCopyGenericsFrom, builder.DefineGenericParameters); } public static GenericTypeParameterBuilder[] CopyGenericArguments( MethodInfo methodToCopyGenericsFrom, MethodBuilder builder) { - var _ = new Dictionary(); - return CopyGenericArguments(methodToCopyGenericsFrom, _, builder.DefineGenericParameters); + return CopyGenericArguments(methodToCopyGenericsFrom, builder.DefineGenericParameters); } private static Type AdjustConstraintToNewGenericParameters( @@ -107,7 +104,6 @@ private static Type[] AdjustGenericConstraints(MethodInfo methodToCopyGenericsFr private static GenericTypeParameterBuilder[] CopyGenericArguments( MethodInfo methodToCopyGenericsFrom, - Dictionary name2GenericType, ApplyGenArgs genericParameterGenerator) { var originalGenericArguments = methodToCopyGenericsFrom.GetGenericArguments(); @@ -136,8 +132,6 @@ private static GenericTypeParameterBuilder[] CopyGenericArguments( newGenericParameters[i].SetGenericParameterAttributes(GenericParameterAttributes.None); } - - name2GenericType[argumentNames[i]] = newGenericParameters[i]; } return newGenericParameters; From c3780f15de8454e76c697d741077ec1df6bba115 Mon Sep 17 00:00:00 2001 From: Dominique Schuppli Date: Mon, 22 Feb 2021 20:43:51 +0100 Subject: [PATCH 9/9] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 68dfe004c6..700f27ac45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ Enhancements: - Significant performance improvements with proxy type generation for interface proxies without target. (Up until now, DynamicProxy generated a separate `IInvocation` implementation type for every single proxied method – it is now able to reuse a single predefined type in many cases, thereby reducing the total amount of dynamic type generation.) (@stakx, #573) Bugfixes: +- Generic method with differently named generic arguments to parent throws `KeyNotFoundException` (@stakx, #106) - Proxying certain `[Serializable]` classes produces proxy types that fail PEVerify test (@stakx, #367) - `private protected` methods are not intercepted (@CrispyDrone, #535) - `System.UIntPtr` unsupported (@stakx, #546)