From 03f8b6ab8e4b511e70a7a0636b7f15663ef8b68f Mon Sep 17 00:00:00 2001 From: Dominique Schuppli Date: Sun, 21 Dec 2025 16:39:40 +0100 Subject: [PATCH 1/9] Remove sequential coupling in `IMemberEmitter` If `EnsureValidCodeBlock` needs to be called before `Generate`, why not simply delegate that responsibility to the `Generate` implementations themselves? --- .../Generators/Emitters/AbstractTypeEmitter.cs | 6 +----- .../Generators/Emitters/ConstructorEmitter.cs | 4 +++- .../Generators/Emitters/EventEmitter.cs | 6 +++--- .../Generators/Emitters/IMemberEmitter.cs | 4 +--- .../Generators/Emitters/MethodEmitter.cs | 4 +++- .../Generators/Emitters/PropertyEmitter.cs | 13 +++---------- 6 files changed, 14 insertions(+), 23 deletions(-) diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/AbstractTypeEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/AbstractTypeEmitter.cs index 361a6bdf8e..6e23de5131 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/AbstractTypeEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/AbstractTypeEmitter.cs @@ -1,4 +1,4 @@ -// Copyright 2004-2021 Castle Project - http://www.castleproject.org/ +// Copyright 2004-2025 Castle Project - http://www.castleproject.org/ // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -351,22 +351,18 @@ protected virtual void EnsureBuildersAreInAValidState() foreach (IMemberEmitter builder in properties) { - builder.EnsureValidCodeBlock(); builder.Generate(); } foreach (IMemberEmitter builder in events) { - builder.EnsureValidCodeBlock(); builder.Generate(); } foreach (IMemberEmitter builder in constructors) { - builder.EnsureValidCodeBlock(); builder.Generate(); } foreach (IMemberEmitter builder in methods) { - builder.EnsureValidCodeBlock(); builder.Generate(); } } diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/ConstructorEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/ConstructorEmitter.cs index 74b2edac37..2cd6bd0916 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/ConstructorEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/ConstructorEmitter.cs @@ -1,4 +1,4 @@ -// Copyright 2004-2021 Castle Project - http://www.castleproject.org/ +// Copyright 2004-2025 Castle Project - http://www.castleproject.org/ // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -83,6 +83,8 @@ public virtual void EnsureValidCodeBlock() public virtual void Generate() { + EnsureValidCodeBlock(); + if (ImplementedByRuntime) { return; diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/EventEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/EventEmitter.cs index 08ad72ea3e..6d23174365 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/EventEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/EventEmitter.cs @@ -1,4 +1,4 @@ -// Copyright 2004-2021 Castle Project - http://www.castleproject.org/ +// Copyright 2004-2025 Castle Project - http://www.castleproject.org/ // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -75,12 +75,12 @@ public MethodEmitter CreateRemoveMethod(string removeMethodName, MethodAttribute public void EnsureValidCodeBlock() { - addMethod.EnsureValidCodeBlock(); - removeMethod.EnsureValidCodeBlock(); } public void Generate() { + EnsureValidCodeBlock(); + if (addMethod == null) { throw new InvalidOperationException("Event add method was not created"); diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/IMemberEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/IMemberEmitter.cs index 9f6676a1a1..e28b3fcf45 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/IMemberEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/IMemberEmitter.cs @@ -1,4 +1,4 @@ -// Copyright 2004-2021 Castle Project - http://www.castleproject.org/ +// Copyright 2004-2025 Castle Project - http://www.castleproject.org/ // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -23,8 +23,6 @@ internal interface IMemberEmitter Type ReturnType { get; } - void EnsureValidCodeBlock(); - void Generate(); } } \ No newline at end of file diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/MethodEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/MethodEmitter.cs index 7d2579f10f..64bdd0ca2d 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/MethodEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/MethodEmitter.cs @@ -1,4 +1,4 @@ -// Copyright 2004-2021 Castle Project - http://www.castleproject.org/ +// Copyright 2004-2025 Castle Project - http://www.castleproject.org/ // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -141,6 +141,8 @@ public virtual void EnsureValidCodeBlock() public virtual void Generate() { + EnsureValidCodeBlock(); + if (ImplementedByRuntime) { return; diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/PropertyEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/PropertyEmitter.cs index c2674b3dea..738ac64c11 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/PropertyEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/PropertyEmitter.cs @@ -1,4 +1,4 @@ -// Copyright 2004-2021 Castle Project - http://www.castleproject.org/ +// Copyright 2004-2025 Castle Project - http://www.castleproject.org/ // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -87,19 +87,12 @@ public void DefineCustomAttribute(CustomAttributeBuilder attribute) public void EnsureValidCodeBlock() { - if (setMethod != null) - { - setMethod.EnsureValidCodeBlock(); - } - - if (getMethod != null) - { - getMethod.EnsureValidCodeBlock(); - } } public void Generate() { + EnsureValidCodeBlock(); + if (setMethod != null) { setMethod.Generate(); From d9bdb5fba3f71250f2680154ededc6e7d29dc9f2 Mon Sep 17 00:00:00 2001 From: Dominique Schuppli Date: Sun, 21 Dec 2025 16:44:27 +0100 Subject: [PATCH 2/9] Inline `EnsureValidCodeBlock` into `Generate` --- .../Generators/Emitters/ConstructorEmitter.cs | 21 +++++++++---------- .../Generators/Emitters/EventEmitter.cs | 6 ------ .../Generators/Emitters/MethodEmitter.cs | 19 +++++++---------- .../Generators/Emitters/PropertyEmitter.cs | 6 ------ .../Emitters/TypeConstructorEmitter.cs | 12 +---------- 5 files changed, 18 insertions(+), 46 deletions(-) diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/ConstructorEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/ConstructorEmitter.cs index 2cd6bd0916..6a3092b484 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/ConstructorEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/ConstructorEmitter.cs @@ -72,24 +72,23 @@ private bool ImplementedByRuntime } } - public virtual void EnsureValidCodeBlock() - { - if (ImplementedByRuntime == false && CodeBuilder.IsEmpty) - { - CodeBuilder.AddStatement(new ConstructorInvocationStatement(mainType.BaseType)); - CodeBuilder.AddStatement(new ReturnStatement()); - } - } - public virtual void Generate() { - EnsureValidCodeBlock(); - if (ImplementedByRuntime) { return; } + if (CodeBuilder.IsEmpty) + { + if (builder.IsStatic == false) + { + CodeBuilder.AddStatement(new ConstructorInvocationStatement(mainType.BaseType)); + } + + CodeBuilder.AddStatement(new ReturnStatement()); + } + CodeBuilder.Generate(builder.GetILGenerator()); } } diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/EventEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/EventEmitter.cs index 6d23174365..c1ff059af8 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/EventEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/EventEmitter.cs @@ -73,14 +73,8 @@ public MethodEmitter CreateRemoveMethod(string removeMethodName, MethodAttribute return removeMethod; } - public void EnsureValidCodeBlock() - { - } - public void Generate() { - EnsureValidCodeBlock(); - if (addMethod == null) { throw new InvalidOperationException("Event add method was not created"); diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/MethodEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/MethodEmitter.cs index 64bdd0ca2d..24b593282b 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/MethodEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/MethodEmitter.cs @@ -124,9 +124,14 @@ public void SetParameters(Type[] paramTypes) ArgumentsUtil.InitializeArgumentsByPosition(arguments, MethodBuilder.IsStatic); } - public virtual void EnsureValidCodeBlock() + public virtual void Generate() { - if (ImplementedByRuntime == false && CodeBuilder.IsEmpty) + if (ImplementedByRuntime) + { + return; + } + + if (CodeBuilder.IsEmpty) { if (ReturnType == typeof(void)) { @@ -137,16 +142,6 @@ public virtual void EnsureValidCodeBlock() CodeBuilder.AddStatement(new ReturnStatement(new DefaultValueExpression(ReturnType))); } } - } - - public virtual void Generate() - { - EnsureValidCodeBlock(); - - if (ImplementedByRuntime) - { - return; - } codeBuilder.Generate(builder.GetILGenerator()); } diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/PropertyEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/PropertyEmitter.cs index 738ac64c11..eb32fcd8a8 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/PropertyEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/PropertyEmitter.cs @@ -85,14 +85,8 @@ public void DefineCustomAttribute(CustomAttributeBuilder attribute) builder.SetCustomAttribute(attribute); } - public void EnsureValidCodeBlock() - { - } - public void Generate() { - EnsureValidCodeBlock(); - if (setMethod != null) { setMethod.Generate(); diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/TypeConstructorEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/TypeConstructorEmitter.cs index 2167a63a35..bf71b7a647 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/TypeConstructorEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/TypeConstructorEmitter.cs @@ -1,4 +1,4 @@ -// Copyright 2004-2021 Castle Project - http://www.castleproject.org/ +// Copyright 2004-2025 Castle Project - http://www.castleproject.org/ // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -14,21 +14,11 @@ namespace Castle.DynamicProxy.Generators.Emitters { - using Castle.DynamicProxy.Generators.Emitters.SimpleAST; - internal class TypeConstructorEmitter : ConstructorEmitter { internal TypeConstructorEmitter(AbstractTypeEmitter mainType) : base(mainType, mainType.TypeBuilder.DefineTypeInitializer()) { } - - public override void EnsureValidCodeBlock() - { - if (CodeBuilder.IsEmpty) - { - CodeBuilder.AddStatement(new ReturnStatement()); - } - } } } \ No newline at end of file From 2a62193e892b1fde77417735a3a6611ee6ab6fa0 Mon Sep 17 00:00:00 2001 From: Dominique Schuppli Date: Sun, 21 Dec 2025 21:51:17 +0100 Subject: [PATCH 3/9] Inline `TypeConstructorEmitter` --- .../Emitters/AbstractTypeEmitter.cs | 4 ++-- .../Emitters/TypeConstructorEmitter.cs | 24 ------------------- 2 files changed, 2 insertions(+), 26 deletions(-) delete mode 100644 src/Castle.Core/DynamicProxy/Generators/Emitters/TypeConstructorEmitter.cs diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/AbstractTypeEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/AbstractTypeEmitter.cs index 6e23de5131..0a09a16cbb 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/AbstractTypeEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/AbstractTypeEmitter.cs @@ -64,7 +64,7 @@ public Type BaseType } } - public TypeConstructorEmitter ClassConstructor { get; private set; } + public ConstructorEmitter ClassConstructor { get; private set; } public GenericTypeParameterBuilder[] GenericTypeParams { @@ -212,7 +212,7 @@ public FieldReference CreateStaticField(string name, Type fieldType, FieldAttrib public ConstructorEmitter CreateTypeConstructor() { - var member = new TypeConstructorEmitter(this); + var member = new ConstructorEmitter(this, TypeBuilder.DefineTypeInitializer()); constructors.Add(member); ClassConstructor = member; return member; diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/TypeConstructorEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/TypeConstructorEmitter.cs deleted file mode 100644 index bf71b7a647..0000000000 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/TypeConstructorEmitter.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2004-2025 Castle Project - http://www.castleproject.org/ -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -namespace Castle.DynamicProxy.Generators.Emitters -{ - internal class TypeConstructorEmitter : ConstructorEmitter - { - internal TypeConstructorEmitter(AbstractTypeEmitter mainType) - : base(mainType, mainType.TypeBuilder.DefineTypeInitializer()) - { - } - } -} \ No newline at end of file From dfbdf0ba80f143a2197e695c6cec9bbd926e7e50 Mon Sep 17 00:00:00 2001 From: Dominique Schuppli Date: Sun, 21 Dec 2025 17:26:42 +0100 Subject: [PATCH 4/9] Remove `IMemberEmitter.ReturnType` ... as it is not applicable to all member types. --- .../DynamicProxy/Generators/Emitters/ConstructorEmitter.cs | 5 ----- .../DynamicProxy/Generators/Emitters/EventEmitter.cs | 7 ------- .../DynamicProxy/Generators/Emitters/IMemberEmitter.cs | 3 --- .../DynamicProxy/Generators/Emitters/PropertyEmitter.cs | 5 ----- 4 files changed, 20 deletions(-) diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/ConstructorEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/ConstructorEmitter.cs index 6a3092b484..c00df69f70 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/ConstructorEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/ConstructorEmitter.cs @@ -58,11 +58,6 @@ public MemberInfo Member get { return builder; } } - public Type ReturnType - { - get { return typeof(void); } - } - private bool ImplementedByRuntime { get diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/EventEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/EventEmitter.cs index c1ff059af8..55833c7b46 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/EventEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/EventEmitter.cs @@ -21,7 +21,6 @@ namespace Castle.DynamicProxy.Generators.Emitters internal class EventEmitter : IMemberEmitter { private readonly EventBuilder eventBuilder; - private readonly Type type; private readonly AbstractTypeEmitter typeEmitter; private MethodEmitter addMethod; private MethodEmitter removeMethod; @@ -37,7 +36,6 @@ public EventEmitter(AbstractTypeEmitter typeEmitter, string name, EventAttribute throw new ArgumentNullException(nameof(type)); } this.typeEmitter = typeEmitter; - this.type = type; eventBuilder = typeEmitter.TypeBuilder.DefineEvent(name, attributes, type); } @@ -46,11 +44,6 @@ public MemberInfo Member get { return null; } } - public Type ReturnType - { - get { return type; } - } - public MethodEmitter CreateAddMethod(string addMethodName, MethodAttributes attributes, MethodInfo methodToOverride) { if (addMethod != null) diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/IMemberEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/IMemberEmitter.cs index e28b3fcf45..77e82e1a97 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/IMemberEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/IMemberEmitter.cs @@ -14,15 +14,12 @@ namespace Castle.DynamicProxy.Generators.Emitters { - using System; using System.Reflection; internal interface IMemberEmitter { MemberInfo Member { get; } - Type ReturnType { get; } - void Generate(); } } \ No newline at end of file diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/PropertyEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/PropertyEmitter.cs index eb32fcd8a8..25b0356d79 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/PropertyEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/PropertyEmitter.cs @@ -40,11 +40,6 @@ public MemberInfo Member get { return null; } } - public Type ReturnType - { - get { return builder.PropertyType; } - } - public MethodEmitter CreateGetMethod(string name, MethodAttributes attrs, MethodInfo methodToOverride, params Type[] parameters) { From ff12b1b86013cd4618e5c60a44fcba5ca3b5119a Mon Sep 17 00:00:00 2001 From: Dominique Schuppli Date: Sun, 21 Dec 2025 17:34:09 +0100 Subject: [PATCH 5/9] Remove superfluous `IMemberEmitter.Member` & impls --- .../DynamicProxy/Generators/Emitters/ConstructorEmitter.cs | 5 ----- .../DynamicProxy/Generators/Emitters/EventEmitter.cs | 5 ----- .../DynamicProxy/Generators/Emitters/IMemberEmitter.cs | 4 ---- .../DynamicProxy/Generators/Emitters/MethodEmitter.cs | 5 ----- .../DynamicProxy/Generators/Emitters/PropertyEmitter.cs | 5 ----- 5 files changed, 24 deletions(-) diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/ConstructorEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/ConstructorEmitter.cs index c00df69f70..c275c5f724 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/ConstructorEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/ConstructorEmitter.cs @@ -53,11 +53,6 @@ public ConstructorBuilder ConstructorBuilder get { return builder; } } - public MemberInfo Member - { - get { return builder; } - } - private bool ImplementedByRuntime { get diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/EventEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/EventEmitter.cs index 55833c7b46..e5df0b4212 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/EventEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/EventEmitter.cs @@ -39,11 +39,6 @@ public EventEmitter(AbstractTypeEmitter typeEmitter, string name, EventAttribute eventBuilder = typeEmitter.TypeBuilder.DefineEvent(name, attributes, type); } - public MemberInfo Member - { - get { return null; } - } - public MethodEmitter CreateAddMethod(string addMethodName, MethodAttributes attributes, MethodInfo methodToOverride) { if (addMethod != null) diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/IMemberEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/IMemberEmitter.cs index 77e82e1a97..5086402a16 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/IMemberEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/IMemberEmitter.cs @@ -14,12 +14,8 @@ namespace Castle.DynamicProxy.Generators.Emitters { - using System.Reflection; - internal interface IMemberEmitter { - MemberInfo Member { get; } - void Generate(); } } \ No newline at end of file diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/MethodEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/MethodEmitter.cs index 24b593282b..c6f3610151 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/MethodEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/MethodEmitter.cs @@ -93,11 +93,6 @@ public MethodBuilder MethodBuilder get { return builder; } } - public MemberInfo Member - { - get { return builder; } - } - public Type ReturnType { get { return builder.ReturnType; } diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/PropertyEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/PropertyEmitter.cs index 25b0356d79..ae8687e93f 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/PropertyEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/PropertyEmitter.cs @@ -35,11 +35,6 @@ public PropertyEmitter(AbstractTypeEmitter parentTypeEmitter, string name, Prope null, null, arguments, null, null); } - public MemberInfo Member - { - get { return null; } - } - public MethodEmitter CreateGetMethod(string name, MethodAttributes attrs, MethodInfo methodToOverride, params Type[] parameters) { From acfc78f60489b2a0da091025a25f0b0552b75db0 Mon Sep 17 00:00:00 2001 From: Dominique Schuppli Date: Sun, 21 Dec 2025 17:36:36 +0100 Subject: [PATCH 6/9] Remove `IMemberEmitter` altogether --- .../Emitters/AbstractTypeEmitter.cs | 8 +++---- .../Generators/Emitters/ConstructorEmitter.cs | 2 +- .../Generators/Emitters/EventEmitter.cs | 2 +- .../Generators/Emitters/IMemberEmitter.cs | 21 ------------------- .../Generators/Emitters/MethodEmitter.cs | 2 +- .../Generators/Emitters/PropertyEmitter.cs | 2 +- 6 files changed, 8 insertions(+), 29 deletions(-) delete mode 100644 src/Castle.Core/DynamicProxy/Generators/Emitters/IMemberEmitter.cs diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/AbstractTypeEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/AbstractTypeEmitter.cs index 0a09a16cbb..d64e4af930 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/AbstractTypeEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/AbstractTypeEmitter.cs @@ -349,19 +349,19 @@ protected virtual void EnsureBuildersAreInAValidState() CreateDefaultConstructor(); } - foreach (IMemberEmitter builder in properties) + foreach (var builder in properties) { builder.Generate(); } - foreach (IMemberEmitter builder in events) + foreach (var builder in events) { builder.Generate(); } - foreach (IMemberEmitter builder in constructors) + foreach (var builder in constructors) { builder.Generate(); } - foreach (IMemberEmitter builder in methods) + foreach (var builder in methods) { builder.Generate(); } diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/ConstructorEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/ConstructorEmitter.cs index c275c5f724..98646c1d9d 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/ConstructorEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/ConstructorEmitter.cs @@ -20,7 +20,7 @@ namespace Castle.DynamicProxy.Generators.Emitters using Castle.DynamicProxy.Generators.Emitters.SimpleAST; - internal class ConstructorEmitter : IMemberEmitter + internal class ConstructorEmitter { private readonly ConstructorBuilder builder; private readonly CodeBuilder codeBuilder; diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/EventEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/EventEmitter.cs index e5df0b4212..272f07bcf3 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/EventEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/EventEmitter.cs @@ -18,7 +18,7 @@ namespace Castle.DynamicProxy.Generators.Emitters using System.Reflection; using System.Reflection.Emit; - internal class EventEmitter : IMemberEmitter + internal class EventEmitter { private readonly EventBuilder eventBuilder; private readonly AbstractTypeEmitter typeEmitter; diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/IMemberEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/IMemberEmitter.cs deleted file mode 100644 index 5086402a16..0000000000 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/IMemberEmitter.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2004-2025 Castle Project - http://www.castleproject.org/ -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -namespace Castle.DynamicProxy.Generators.Emitters -{ - internal interface IMemberEmitter - { - void Generate(); - } -} \ No newline at end of file diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/MethodEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/MethodEmitter.cs index c6f3610151..1152c93394 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/MethodEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/MethodEmitter.cs @@ -26,7 +26,7 @@ namespace Castle.DynamicProxy.Generators.Emitters using Castle.DynamicProxy.Internal; [DebuggerDisplay("{builder.Name}")] - internal class MethodEmitter : IMemberEmitter + internal class MethodEmitter { private readonly MethodBuilder builder; private readonly CodeBuilder codeBuilder; diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/PropertyEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/PropertyEmitter.cs index ae8687e93f..0da52f94b3 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/PropertyEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/PropertyEmitter.cs @@ -18,7 +18,7 @@ namespace Castle.DynamicProxy.Generators.Emitters using System.Reflection; using System.Reflection.Emit; - internal class PropertyEmitter : IMemberEmitter + internal class PropertyEmitter { private readonly PropertyBuilder builder; private readonly AbstractTypeEmitter parentTypeEmitter; From 963f4b08d953b4a0e87cb6bced2575def52f1109 Mon Sep 17 00:00:00 2001 From: Dominique Schuppli Date: Sun, 21 Dec 2025 17:42:33 +0100 Subject: [PATCH 7/9] Remove unused `NestedClassEmitter` --- .../ClassEmitterTestCase.cs | 19 +------ .../Emitters/AbstractTypeEmitter.cs | 12 ----- .../Generators/Emitters/NestedClassEmitter.cs | 52 ------------------- 3 files changed, 1 insertion(+), 82 deletions(-) delete mode 100644 src/Castle.Core/DynamicProxy/Generators/Emitters/NestedClassEmitter.cs diff --git a/src/Castle.Core.Tests/DynamicProxy.Tests/ClassEmitterTestCase.cs b/src/Castle.Core.Tests/DynamicProxy.Tests/ClassEmitterTestCase.cs index 62d46e1697..75ebd55892 100644 --- a/src/Castle.Core.Tests/DynamicProxy.Tests/ClassEmitterTestCase.cs +++ b/src/Castle.Core.Tests/DynamicProxy.Tests/ClassEmitterTestCase.cs @@ -1,4 +1,4 @@ -// Copyright 2004-2021 Castle Project - http://www.castleproject.org/ +// Copyright 2004-2025 Castle Project - http://www.castleproject.org/ // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -157,22 +157,5 @@ public void NoCustomCtorForInterfaces() emitter.CreateConstructor(); }); } - - [Test] - public void NestedInterface() - { - ClassEmitter outerEmitter = new ClassEmitter(generator.ProxyBuilder.ModuleScope, "IOuter", null, Type.EmptyTypes, - TypeAttributes.Interface | TypeAttributes.Abstract | TypeAttributes.Public, false); - NestedClassEmitter innerEmitter = new NestedClassEmitter(outerEmitter, "IInner", - TypeAttributes.Interface | TypeAttributes.Abstract | TypeAttributes.NestedPublic, null, Type.EmptyTypes); - innerEmitter.CreateMethod("MyMethod", MethodAttributes.Public | MethodAttributes.Abstract | MethodAttributes.Virtual, - typeof(void), Type.EmptyTypes); - Type inner = innerEmitter.BuildType(); - Type outer = outerEmitter.BuildType(); - Assert.IsTrue(inner.IsInterface); - MethodInfo method = inner.GetMethod("MyMethod"); - Assert.IsNotNull(method); - Assert.AreSame(inner, outer.GetNestedType("IInner", BindingFlags.Public)); - } } } \ No newline at end of file diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/AbstractTypeEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/AbstractTypeEmitter.cs index d64e4af930..0440fe3c1a 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 List nested; private readonly List properties; private readonly TypeBuilder typeBuilder; @@ -45,7 +44,6 @@ internal abstract class AbstractTypeEmitter protected AbstractTypeEmitter(TypeBuilder typeBuilder) { this.typeBuilder = typeBuilder; - nested = new List(); methods = new List(); constructors = new List(); properties = new List(); @@ -84,22 +82,12 @@ public void AddCustomAttributes(IEnumerable additionalAttri } } - public void AddNestedClass(NestedClassEmitter nestedClass) - { - nested.Add(nestedClass); - } - public virtual Type BuildType() { EnsureBuildersAreInAValidState(); var type = CreateType(typeBuilder); - foreach (var builder in nested) - { - builder.BuildType(); - } - return type; } diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/NestedClassEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/NestedClassEmitter.cs deleted file mode 100644 index d019a7bfde..0000000000 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/NestedClassEmitter.cs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2004-2021 Castle Project - http://www.castleproject.org/ -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -namespace Castle.DynamicProxy.Generators.Emitters -{ - using System; - using System.Reflection; - using System.Reflection.Emit; - - internal class NestedClassEmitter : AbstractTypeEmitter - { - public NestedClassEmitter(AbstractTypeEmitter mainType, string name, Type baseType, Type[] interfaces) - : this( - mainType, - CreateTypeBuilder(mainType, name, TypeAttributes.Sealed | TypeAttributes.NestedPublic | TypeAttributes.Class, - baseType, interfaces)) - { - } - - public NestedClassEmitter(AbstractTypeEmitter mainType, string name, TypeAttributes attributes, Type baseType, - Type[] interfaces) - : this(mainType, CreateTypeBuilder(mainType, name, attributes, baseType, interfaces)) - { - } - - public NestedClassEmitter(AbstractTypeEmitter mainType, TypeBuilder typeBuilder) - : base(typeBuilder) - { - mainType.AddNestedClass(this); - } - - private static TypeBuilder CreateTypeBuilder(AbstractTypeEmitter mainType, string name, TypeAttributes attributes, - Type baseType, Type[] interfaces) - { - return mainType.TypeBuilder.DefineNestedType( - name, - attributes, - baseType, interfaces); - } - } -} \ No newline at end of file From 17c9423124680e596f1f2fe808e7625c0c2859c6 Mon Sep 17 00:00:00 2001 From: Dominique Schuppli Date: Sun, 21 Dec 2025 17:55:16 +0100 Subject: [PATCH 8/9] Merge `AbstractTypeEmitter` into `ClassEmitter` ... since DynamicProxy does in actual fact not ever generate any types that aren't classes. --- .../ClassEmitterTestCase.cs | 51 --- .../IInvocationCreationContributor.cs | 6 +- .../InvocationWithDelegateContributor.cs | 6 +- ...nvocationWithGenericDelegateContributor.cs | 8 +- .../CompositionInvocationTypeGenerator.cs | 2 +- .../Generators/DelegateTypeGenerator.cs | 14 +- .../Emitters/AbstractTypeEmitter.cs | 358 ----------------- .../Generators/Emitters/ClassEmitter.cs | 361 ++++++++++++++++-- .../Generators/Emitters/ConstructorEmitter.cs | 6 +- .../Generators/Emitters/EventEmitter.cs | 4 +- .../Generators/Emitters/MethodEmitter.cs | 6 +- .../Generators/Emitters/PropertyEmitter.cs | 4 +- .../Generators/InvocationTypeGenerator.cs | 27 +- 13 files changed, 377 insertions(+), 476 deletions(-) delete mode 100644 src/Castle.Core/DynamicProxy/Generators/Emitters/AbstractTypeEmitter.cs diff --git a/src/Castle.Core.Tests/DynamicProxy.Tests/ClassEmitterTestCase.cs b/src/Castle.Core.Tests/DynamicProxy.Tests/ClassEmitterTestCase.cs index 75ebd55892..cef0481ccd 100644 --- a/src/Castle.Core.Tests/DynamicProxy.Tests/ClassEmitterTestCase.cs +++ b/src/Castle.Core.Tests/DynamicProxy.Tests/ClassEmitterTestCase.cs @@ -106,56 +106,5 @@ public void CreateStaticFieldWithAttributes() Assert.IsNotNull(field); Assert.AreEqual(FieldAttributes.Static | FieldAttributes.FamANDAssem | FieldAttributes.InitOnly, field.Attributes); } - - [Test] - public void UsingClassEmitterForInterfaces() - { - ClassEmitter emitter = new ClassEmitter(generator.ProxyBuilder.ModuleScope, "IFoo", null, Type.EmptyTypes, - TypeAttributes.Interface | TypeAttributes.Abstract | TypeAttributes.Public, false); - emitter.CreateMethod("MyMethod", MethodAttributes.Public | MethodAttributes.Abstract | MethodAttributes.Virtual, - typeof(void), Type.EmptyTypes); - Type t = emitter.BuildType(); - Assert.IsTrue(t.IsInterface); - MethodInfo method = t.GetMethod("MyMethod"); - Assert.IsNotNull(method); - } - - [Test] - public void NoBaseTypeForInterfaces() - { - DisableVerification(); - ClassEmitter emitter = new ClassEmitter (generator.ProxyBuilder.ModuleScope, "IFoo", null, Type.EmptyTypes, - TypeAttributes.Interface | TypeAttributes.Abstract | TypeAttributes.Public, false); - - Assert.Throws(delegate { -#pragma warning disable 219 - Type t = emitter.BaseType; -#pragma warning restore 219 - }); - } - - [Test] - public void NoDefaultCtorForInterfaces() - { - DisableVerification(); - ClassEmitter emitter = new ClassEmitter(generator.ProxyBuilder.ModuleScope, "IFoo", null, Type.EmptyTypes, - TypeAttributes.Interface | TypeAttributes.Abstract | TypeAttributes.Public, false); - - Assert.Throws(delegate { - emitter.CreateDefaultConstructor(); - }); - } - - [Test] - public void NoCustomCtorForInterfaces() - { - DisableVerification(); - ClassEmitter emitter = new ClassEmitter(generator.ProxyBuilder.ModuleScope, "IFoo", null, Type.EmptyTypes, - TypeAttributes.Interface | TypeAttributes.Abstract | TypeAttributes.Public, false); - - Assert.Throws(delegate { - emitter.CreateConstructor(); - }); - } } } \ No newline at end of file diff --git a/src/Castle.Core/DynamicProxy/Contributors/IInvocationCreationContributor.cs b/src/Castle.Core/DynamicProxy/Contributors/IInvocationCreationContributor.cs index 87b94f848b..81e62bc7d8 100644 --- a/src/Castle.Core/DynamicProxy/Contributors/IInvocationCreationContributor.cs +++ b/src/Castle.Core/DynamicProxy/Contributors/IInvocationCreationContributor.cs @@ -1,4 +1,4 @@ -// Copyright 2004-2021 Castle Project - http://www.castleproject.org/ +// Copyright 2004-2025 Castle Project - http://www.castleproject.org/ // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -21,11 +21,11 @@ namespace Castle.DynamicProxy.Contributors internal interface IInvocationCreationContributor { - ConstructorEmitter CreateConstructor(ArgumentReference[] baseCtorArguments, AbstractTypeEmitter invocation); + ConstructorEmitter CreateConstructor(ArgumentReference[] baseCtorArguments, ClassEmitter invocation); MethodInfo GetCallbackMethod(); - MethodInvocationExpression GetCallbackMethodInvocation(AbstractTypeEmitter invocation, IExpression[] args, + MethodInvocationExpression GetCallbackMethodInvocation(ClassEmitter invocation, IExpression[] args, Reference targetField, MethodEmitter invokeMethodOnTarget); IExpression[] GetConstructorInvocationArguments(IExpression[] arguments, ClassEmitter proxy); diff --git a/src/Castle.Core/DynamicProxy/Contributors/InvocationWithDelegateContributor.cs b/src/Castle.Core/DynamicProxy/Contributors/InvocationWithDelegateContributor.cs index 48f7d29691..ff5b2db635 100644 --- a/src/Castle.Core/DynamicProxy/Contributors/InvocationWithDelegateContributor.cs +++ b/src/Castle.Core/DynamicProxy/Contributors/InvocationWithDelegateContributor.cs @@ -1,4 +1,4 @@ -// Copyright 2004-2021 Castle Project - http://www.castleproject.org/ +// Copyright 2004-2025 Castle Project - http://www.castleproject.org/ // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -40,7 +40,7 @@ public InvocationWithDelegateContributor(Type delegateType, Type targetType, Met this.namingScope = namingScope; } - public ConstructorEmitter CreateConstructor(ArgumentReference[] baseCtorArguments, AbstractTypeEmitter invocation) + public ConstructorEmitter CreateConstructor(ArgumentReference[] baseCtorArguments, ClassEmitter invocation) { var arguments = GetArguments(baseCtorArguments); var constructor = invocation.CreateConstructor(arguments); @@ -55,7 +55,7 @@ public MethodInfo GetCallbackMethod() return delegateType.GetMethod("Invoke"); } - public MethodInvocationExpression GetCallbackMethodInvocation(AbstractTypeEmitter invocation, IExpression[] args, + public MethodInvocationExpression GetCallbackMethodInvocation(ClassEmitter invocation, IExpression[] args, Reference targetField, MethodEmitter invokeMethodOnTarget) { diff --git a/src/Castle.Core/DynamicProxy/Contributors/InvocationWithGenericDelegateContributor.cs b/src/Castle.Core/DynamicProxy/Contributors/InvocationWithGenericDelegateContributor.cs index 3dbeaf5fe7..fd186aa6ec 100644 --- a/src/Castle.Core/DynamicProxy/Contributors/InvocationWithGenericDelegateContributor.cs +++ b/src/Castle.Core/DynamicProxy/Contributors/InvocationWithGenericDelegateContributor.cs @@ -1,4 +1,4 @@ -// Copyright 2004-2021 Castle Project - http://www.castleproject.org/ +// Copyright 2004-2025 Castle Project - http://www.castleproject.org/ // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -39,7 +39,7 @@ public InvocationWithGenericDelegateContributor(Type delegateType, MetaMethod me this.targetReference = targetReference; } - public ConstructorEmitter CreateConstructor(ArgumentReference[] baseCtorArguments, AbstractTypeEmitter invocation) + public ConstructorEmitter CreateConstructor(ArgumentReference[] baseCtorArguments, ClassEmitter invocation) { return invocation.CreateConstructor(baseCtorArguments); } @@ -49,7 +49,7 @@ public MethodInfo GetCallbackMethod() return delegateType.GetMethod("Invoke"); } - public MethodInvocationExpression GetCallbackMethodInvocation(AbstractTypeEmitter invocation, IExpression[] args, + public MethodInvocationExpression GetCallbackMethodInvocation(ClassEmitter invocation, IExpression[] args, Reference targetField, MethodEmitter invokeMethodOnTarget) { @@ -62,7 +62,7 @@ public IExpression[] GetConstructorInvocationArguments(IExpression[] arguments, return arguments; } - private Reference GetDelegate(AbstractTypeEmitter invocation, MethodEmitter invokeMethodOnTarget) + private Reference GetDelegate(ClassEmitter invocation, MethodEmitter invokeMethodOnTarget) { var genericTypeParameters = invocation.GenericTypeParams.AsTypeArray(); var closedDelegateType = delegateType.MakeGenericType(genericTypeParameters); diff --git a/src/Castle.Core/DynamicProxy/Generators/CompositionInvocationTypeGenerator.cs b/src/Castle.Core/DynamicProxy/Generators/CompositionInvocationTypeGenerator.cs index 93bd20b446..cd3adcc880 100644 --- a/src/Castle.Core/DynamicProxy/Generators/CompositionInvocationTypeGenerator.cs +++ b/src/Castle.Core/DynamicProxy/Generators/CompositionInvocationTypeGenerator.cs @@ -57,7 +57,7 @@ protected override FieldReference GetTargetReference() return new FieldReference(InvocationMethods.CompositionInvocationTarget); } - protected override void ImplementInvokeMethodOnTarget(AbstractTypeEmitter invocation, ParameterInfo[] parameters, + protected override void ImplementInvokeMethodOnTarget(ClassEmitter invocation, ParameterInfo[] parameters, MethodEmitter invokeMethodOnTarget, Reference targetField) { invokeMethodOnTarget.CodeBuilder.AddStatement( diff --git a/src/Castle.Core/DynamicProxy/Generators/DelegateTypeGenerator.cs b/src/Castle.Core/DynamicProxy/Generators/DelegateTypeGenerator.cs index 8efd6d40cf..a18f2ec75c 100644 --- a/src/Castle.Core/DynamicProxy/Generators/DelegateTypeGenerator.cs +++ b/src/Castle.Core/DynamicProxy/Generators/DelegateTypeGenerator.cs @@ -1,4 +1,4 @@ -// Copyright 2004-2021 Castle Project - http://www.castleproject.org/ +// Copyright 2004-2025 Castle Project - http://www.castleproject.org/ // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -21,7 +21,7 @@ namespace Castle.DynamicProxy.Generators using Castle.DynamicProxy.Generators.Emitters.SimpleAST; using Castle.DynamicProxy.Internal; - internal class DelegateTypeGenerator : IGenerator + internal class DelegateTypeGenerator : IGenerator { private const TypeAttributes DelegateFlags = TypeAttributes.Class | TypeAttributes.Public | @@ -38,7 +38,7 @@ public DelegateTypeGenerator(MetaMethod method, Type targetType) this.targetType = targetType; } - public AbstractTypeEmitter Generate(ClassEmitter @class, INamingScope namingScope) + public ClassEmitter Generate(ClassEmitter @class, INamingScope namingScope) { var emitter = GetEmitter(@class, namingScope); BuildConstructor(emitter); @@ -46,14 +46,14 @@ public AbstractTypeEmitter Generate(ClassEmitter @class, INamingScope namingScop return emitter; } - private void BuildConstructor(AbstractTypeEmitter emitter) + private void BuildConstructor(ClassEmitter emitter) { var constructor = emitter.CreateConstructor(new ArgumentReference(typeof(object)), new ArgumentReference(typeof(IntPtr))); constructor.ConstructorBuilder.SetImplementationFlags(MethodImplAttributes.Runtime | MethodImplAttributes.Managed); } - private void BuildInvokeMethod(AbstractTypeEmitter @delegate) + private void BuildInvokeMethod(ClassEmitter @delegate) { var paramTypes = GetParamTypes(@delegate); var invoke = @delegate.CreateMethod("Invoke", @@ -66,7 +66,7 @@ private void BuildInvokeMethod(AbstractTypeEmitter @delegate) invoke.MethodBuilder.SetImplementationFlags(MethodImplAttributes.Runtime | MethodImplAttributes.Managed); } - private AbstractTypeEmitter GetEmitter(ClassEmitter @class, INamingScope namingScope) + private ClassEmitter GetEmitter(ClassEmitter @class, INamingScope namingScope) { var methodInfo = method.MethodOnTarget; var suggestedName = string.Format("Castle.Proxies.Delegates.{0}_{1}", @@ -84,7 +84,7 @@ private AbstractTypeEmitter GetEmitter(ClassEmitter @class, INamingScope namingS return @delegate; } - private Type[] GetParamTypes(AbstractTypeEmitter @delegate) + private Type[] GetParamTypes(ClassEmitter @delegate) { var parameters = method.MethodOnTarget.GetParameters(); if (@delegate.TypeBuilder.IsGenericType) diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/AbstractTypeEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/AbstractTypeEmitter.cs deleted file mode 100644 index 0440fe3c1a..0000000000 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/AbstractTypeEmitter.cs +++ /dev/null @@ -1,358 +0,0 @@ -// Copyright 2004-2025 Castle Project - http://www.castleproject.org/ -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -namespace Castle.DynamicProxy.Generators.Emitters -{ - using System; - using System.Collections.Generic; - using System.Diagnostics; - using System.Reflection; - using System.Reflection.Emit; - - using Castle.DynamicProxy.Generators.Emitters.SimpleAST; - using Castle.DynamicProxy.Internal; - - internal abstract class AbstractTypeEmitter - { - private const MethodAttributes defaultAttributes = - MethodAttributes.HideBySig | MethodAttributes.Virtual | MethodAttributes.Public; - - private readonly List constructors; - private readonly List events; - - private readonly IDictionary fields = - new Dictionary(StringComparer.OrdinalIgnoreCase); - - private readonly List methods; - - private readonly List properties; - private readonly TypeBuilder typeBuilder; - - private GenericTypeParameterBuilder[] genericTypeParams; - - protected AbstractTypeEmitter(TypeBuilder typeBuilder) - { - this.typeBuilder = typeBuilder; - methods = new List(); - constructors = new List(); - properties = new List(); - events = new List(); - } - - public Type BaseType - { - get - { - if (TypeBuilder.IsInterface) - { - throw new InvalidOperationException("This emitter represents an interface; interfaces have no base types."); - } - return TypeBuilder.BaseType; - } - } - - public ConstructorEmitter ClassConstructor { get; private set; } - - public GenericTypeParameterBuilder[] GenericTypeParams - { - get { return genericTypeParams; } - } - - public TypeBuilder TypeBuilder - { - get { return typeBuilder; } - } - - public void AddCustomAttributes(IEnumerable additionalAttributes) - { - foreach (var attribute in additionalAttributes) - { - typeBuilder.SetCustomAttribute(attribute.Builder); - } - } - - public virtual Type BuildType() - { - EnsureBuildersAreInAValidState(); - - var type = CreateType(typeBuilder); - - return type; - } - - public void CopyGenericParametersFromMethod(MethodInfo methodToCopyGenericsFrom) - { - // big sanity check - if (genericTypeParams != null) - { - throw new InvalidOperationException("Cannot invoke me twice"); - } - - SetGenericTypeParameters(GenericUtil.CopyGenericArguments(methodToCopyGenericsFrom, typeBuilder)); - } - - public ConstructorEmitter CreateConstructor(params ArgumentReference[] arguments) - { - if (TypeBuilder.IsInterface) - { - throw new InvalidOperationException("Interfaces cannot have constructors."); - } - - var member = new ConstructorEmitter(this, arguments); - constructors.Add(member); - return member; - } - - public void CreateDefaultConstructor() - { - if (TypeBuilder.IsInterface) - { - throw new InvalidOperationException("Interfaces cannot have constructors."); - } - - constructors.Add(new ConstructorEmitter(this)); - } - - public EventEmitter CreateEvent(string name, EventAttributes atts, Type type) - { - var eventEmitter = new EventEmitter(this, name, atts, type); - events.Add(eventEmitter); - return eventEmitter; - } - - public FieldReference CreateField(string name, Type fieldType) - { - return CreateField(name, fieldType, true); - } - - public FieldReference CreateField(string name, Type fieldType, bool serializable) - { - var atts = FieldAttributes.Private; - - if (!serializable) - { - atts |= FieldAttributes.NotSerialized; - } - - return CreateField(name, fieldType, atts); - } - - public FieldReference CreateField(string name, Type fieldType, FieldAttributes atts) - { - var fieldBuilder = typeBuilder.DefineField(name, fieldType, atts); - var reference = new FieldReference(fieldBuilder); - fields[name] = reference; - return reference; - } - - public MethodEmitter CreateMethod(string name, MethodAttributes attrs, Type returnType, params Type[] argumentTypes) - { - var member = new MethodEmitter(this, name, attrs, returnType, argumentTypes ?? Type.EmptyTypes); - methods.Add(member); - return member; - } - - public MethodEmitter CreateMethod(string name, Type returnType, params Type[] parameterTypes) - { - return CreateMethod(name, defaultAttributes, returnType, parameterTypes); - } - - public MethodEmitter CreateMethod(string name, MethodInfo methodToUseAsATemplate) - { - return CreateMethod(name, defaultAttributes, methodToUseAsATemplate); - } - - public MethodEmitter CreateMethod(string name, MethodAttributes attributes, MethodInfo methodToUseAsATemplate) - { - var method = new MethodEmitter(this, name, attributes, methodToUseAsATemplate); - methods.Add(method); - return method; - } - - public PropertyEmitter CreateProperty(string name, PropertyAttributes attributes, Type propertyType, Type[] arguments) - { - var propEmitter = new PropertyEmitter(this, name, attributes, propertyType, arguments); - properties.Add(propEmitter); - return propEmitter; - } - - public FieldReference CreateStaticField(string name, Type fieldType) - { - return CreateStaticField(name, fieldType, FieldAttributes.Private); - } - - public FieldReference CreateStaticField(string name, Type fieldType, FieldAttributes atts) - { - atts |= FieldAttributes.Static; - return CreateField(name, fieldType, atts); - } - - public ConstructorEmitter CreateTypeConstructor() - { - var member = new ConstructorEmitter(this, TypeBuilder.DefineTypeInitializer()); - constructors.Add(member); - ClassConstructor = member; - return member; - } - - public void DefineCustomAttribute(CustomAttributeBuilder attribute) - { - typeBuilder.SetCustomAttribute(attribute); - } - - public void DefineCustomAttribute(object[] constructorArguments) where TAttribute : Attribute - { - var customAttributeInfo = AttributeUtil.CreateInfo(typeof(TAttribute), constructorArguments); - typeBuilder.SetCustomAttribute(customAttributeInfo.Builder); - } - - public void DefineCustomAttribute() where TAttribute : Attribute, new() - { - var customAttributeInfo = AttributeUtil.CreateInfo(); - typeBuilder.SetCustomAttribute(customAttributeInfo.Builder); - } - - public void DefineCustomAttributeFor(FieldReference field) where TAttribute : Attribute, new() - { - var customAttributeInfo = AttributeUtil.CreateInfo(); - var fieldBuilder = field.FieldBuilder; - if (fieldBuilder == null) - { - throw new ArgumentException( - "Invalid field reference.This reference does not point to field on type being generated", nameof(field)); - } - fieldBuilder.SetCustomAttribute(customAttributeInfo.Builder); - } - - public IEnumerable GetAllFields() - { - return fields.Values; - } - - public FieldReference GetField(string name) - { - if (string.IsNullOrEmpty(name)) - { - return null; - } - - FieldReference value; - fields.TryGetValue(name, out value); - return value; - } - - public Type GetClosedParameterType(Type 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)) - { - return parameter.GetGenericTypeDefinition().MakeGenericType(arguments); - } - } - - if (parameter.IsGenericParameter) - { - return GetGenericArgument(parameter.GenericParameterPosition); - } - - 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(int position) - { - Debug.Assert(0 <= position && position < genericTypeParams.Length); - - return genericTypeParams[position]; - } - - public Type[] GetGenericArgumentsFor(MethodInfo genericMethod) - { - Debug.Assert(genericMethod.GetGenericArguments().Length == genericTypeParams.Length); - - return genericTypeParams; - } - - public void SetGenericTypeParameters(GenericTypeParameterBuilder[] genericTypeParameterBuilders) - { - genericTypeParams = genericTypeParameterBuilders; - } - - protected Type CreateType(TypeBuilder type) - { - return type.CreateTypeInfo(); - } - - protected virtual void EnsureBuildersAreInAValidState() - { - if (!typeBuilder.IsInterface && constructors.Count == 0) - { - CreateDefaultConstructor(); - } - - foreach (var builder in properties) - { - builder.Generate(); - } - foreach (var builder in events) - { - builder.Generate(); - } - foreach (var builder in constructors) - { - builder.Generate(); - } - foreach (var builder in methods) - { - builder.Generate(); - } - } - } -} \ No newline at end of file diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/ClassEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/ClassEmitter.cs index 07a658aee4..8b23dcadc8 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/ClassEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/ClassEmitter.cs @@ -1,4 +1,4 @@ -// Copyright 2004-2021 Castle Project - http://www.castleproject.org/ +// Copyright 2004-2025 Castle Project - http://www.castleproject.org/ // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -20,23 +20,44 @@ namespace Castle.DynamicProxy.Generators.Emitters using System.Reflection; using System.Reflection.Emit; + using Castle.DynamicProxy.Generators.Emitters.SimpleAST; using Castle.DynamicProxy.Internal; - internal class ClassEmitter : AbstractTypeEmitter + internal sealed class ClassEmitter { - internal const TypeAttributes DefaultAttributes = - TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.Serializable; + private const MethodAttributes defaultAttributes = + MethodAttributes.HideBySig | MethodAttributes.Virtual | MethodAttributes.Public; private readonly ModuleScope moduleScope; - public ClassEmitter(ModuleScope moduleScope, string name, Type baseType, IEnumerable interfaces) - : this(moduleScope, name, baseType, interfaces, DefaultAttributes, forceUnsigned: false) + private readonly List constructors; + private readonly List events; + + private readonly IDictionary fields = + new Dictionary(StringComparer.OrdinalIgnoreCase); + + private readonly List methods; + + private readonly List properties; + private readonly TypeBuilder typeBuilder; + + private GenericTypeParameterBuilder[] genericTypeParams; + + internal const TypeAttributes DefaultTypeAttributes = + TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.Serializable; + + public ClassEmitter(TypeBuilder typeBuilder) { + Debug.Assert(typeBuilder.IsClass, $"{nameof(ClassEmitter)} only supports class types."); + + this.typeBuilder = typeBuilder; + methods = new List(); + constructors = new List(); + properties = new List(); + events = new List(); } - public ClassEmitter(ModuleScope moduleScope, string name, Type baseType, IEnumerable interfaces, - TypeAttributes flags, - bool forceUnsigned) + public ClassEmitter(ModuleScope moduleScope, string name, Type baseType, IEnumerable interfaces, TypeAttributes flags, bool forceUnsigned) : this(CreateTypeBuilder(moduleScope, name, baseType, interfaces, flags, forceUnsigned)) { interfaces = InitializeGenericArgumentsFromBases(ref baseType, interfaces); @@ -60,23 +81,12 @@ public ClassEmitter(ModuleScope moduleScope, string name, Type baseType, IEnumer this.moduleScope = moduleScope; } - public ClassEmitter(TypeBuilder typeBuilder) - : base(typeBuilder) - { - } - - public ModuleScope ModuleScope - { - get { return moduleScope; } - } - - internal bool InStrongNamedModule + public ClassEmitter(ModuleScope moduleScope, string name, Type baseType, IEnumerable interfaces) + : this(moduleScope, name, baseType, interfaces, DefaultTypeAttributes, forceUnsigned: false) { - get { return StrongNameUtil.IsAssemblySigned(TypeBuilder.Assembly); } } - protected virtual IEnumerable InitializeGenericArgumentsFromBases(ref Type baseType, - IEnumerable interfaces) + private static IEnumerable InitializeGenericArgumentsFromBases(ref Type baseType, IEnumerable interfaces) { if (baseType != null && baseType.IsGenericTypeDefinition) { @@ -99,11 +109,312 @@ protected virtual IEnumerable InitializeGenericArgumentsFromBases(ref Type } private static TypeBuilder CreateTypeBuilder(ModuleScope moduleScope, string name, Type baseType, - IEnumerable interfaces, - TypeAttributes flags, bool forceUnsigned) + IEnumerable interfaces, + TypeAttributes flags, bool forceUnsigned) { var isAssemblySigned = !forceUnsigned && !StrongNameUtil.IsAnyTypeFromUnsignedAssembly(baseType, interfaces); return moduleScope.DefineType(isAssemblySigned, name, flags); } + + public Type BaseType + { + get + { + return TypeBuilder.BaseType; + } + } + + public ConstructorEmitter ClassConstructor { get; private set; } + + internal bool InStrongNamedModule + { + get { return StrongNameUtil.IsAssemblySigned(TypeBuilder.Assembly); } + } + + public GenericTypeParameterBuilder[] GenericTypeParams + { + get { return genericTypeParams; } + } + + public ModuleScope ModuleScope + { + get { return moduleScope; } + } + + public TypeBuilder TypeBuilder + { + get { return typeBuilder; } + } + + public void AddCustomAttributes(IEnumerable additionalAttributes) + { + foreach (var attribute in additionalAttributes) + { + typeBuilder.SetCustomAttribute(attribute.Builder); + } + } + + public Type BuildType() + { + EnsureBuildersAreInAValidState(); + + var type = CreateType(typeBuilder); + + return type; + } + + public void CopyGenericParametersFromMethod(MethodInfo methodToCopyGenericsFrom) + { + // big sanity check + if (genericTypeParams != null) + { + throw new InvalidOperationException("Cannot invoke me twice"); + } + + SetGenericTypeParameters(GenericUtil.CopyGenericArguments(methodToCopyGenericsFrom, typeBuilder)); + } + + public ConstructorEmitter CreateConstructor(params ArgumentReference[] arguments) + { + var member = new ConstructorEmitter(this, arguments); + constructors.Add(member); + return member; + } + + public void CreateDefaultConstructor() + { + constructors.Add(new ConstructorEmitter(this)); + } + + public EventEmitter CreateEvent(string name, EventAttributes atts, Type type) + { + var eventEmitter = new EventEmitter(this, name, atts, type); + events.Add(eventEmitter); + return eventEmitter; + } + + public FieldReference CreateField(string name, Type fieldType) + { + return CreateField(name, fieldType, true); + } + + public FieldReference CreateField(string name, Type fieldType, bool serializable) + { + var atts = FieldAttributes.Private; + + if (!serializable) + { + atts |= FieldAttributes.NotSerialized; + } + + return CreateField(name, fieldType, atts); + } + + public FieldReference CreateField(string name, Type fieldType, FieldAttributes atts) + { + var fieldBuilder = typeBuilder.DefineField(name, fieldType, atts); + var reference = new FieldReference(fieldBuilder); + fields[name] = reference; + return reference; + } + + public MethodEmitter CreateMethod(string name, MethodAttributes attrs, Type returnType, params Type[] argumentTypes) + { + var member = new MethodEmitter(this, name, attrs, returnType, argumentTypes ?? Type.EmptyTypes); + methods.Add(member); + return member; + } + + public MethodEmitter CreateMethod(string name, Type returnType, params Type[] parameterTypes) + { + return CreateMethod(name, defaultAttributes, returnType, parameterTypes); + } + + public MethodEmitter CreateMethod(string name, MethodInfo methodToUseAsATemplate) + { + return CreateMethod(name, defaultAttributes, methodToUseAsATemplate); + } + + public MethodEmitter CreateMethod(string name, MethodAttributes attributes, MethodInfo methodToUseAsATemplate) + { + var method = new MethodEmitter(this, name, attributes, methodToUseAsATemplate); + methods.Add(method); + return method; + } + + public PropertyEmitter CreateProperty(string name, PropertyAttributes attributes, Type propertyType, Type[] arguments) + { + var propEmitter = new PropertyEmitter(this, name, attributes, propertyType, arguments); + properties.Add(propEmitter); + return propEmitter; + } + + public FieldReference CreateStaticField(string name, Type fieldType) + { + return CreateStaticField(name, fieldType, FieldAttributes.Private); + } + + public FieldReference CreateStaticField(string name, Type fieldType, FieldAttributes atts) + { + atts |= FieldAttributes.Static; + return CreateField(name, fieldType, atts); + } + + public ConstructorEmitter CreateTypeConstructor() + { + var member = new ConstructorEmitter(this, TypeBuilder.DefineTypeInitializer()); + constructors.Add(member); + ClassConstructor = member; + return member; + } + + public void DefineCustomAttribute(CustomAttributeBuilder attribute) + { + typeBuilder.SetCustomAttribute(attribute); + } + + public void DefineCustomAttribute(object[] constructorArguments) where TAttribute : Attribute + { + var customAttributeInfo = AttributeUtil.CreateInfo(typeof(TAttribute), constructorArguments); + typeBuilder.SetCustomAttribute(customAttributeInfo.Builder); + } + + public void DefineCustomAttribute() where TAttribute : Attribute, new() + { + var customAttributeInfo = AttributeUtil.CreateInfo(); + typeBuilder.SetCustomAttribute(customAttributeInfo.Builder); + } + + public void DefineCustomAttributeFor(FieldReference field) where TAttribute : Attribute, new() + { + var customAttributeInfo = AttributeUtil.CreateInfo(); + var fieldBuilder = field.FieldBuilder; + if (fieldBuilder == null) + { + throw new ArgumentException( + "Invalid field reference.This reference does not point to field on type being generated", nameof(field)); + } + fieldBuilder.SetCustomAttribute(customAttributeInfo.Builder); + } + + public IEnumerable GetAllFields() + { + return fields.Values; + } + + public FieldReference GetField(string name) + { + if (string.IsNullOrEmpty(name)) + { + return null; + } + + FieldReference value; + fields.TryGetValue(name, out value); + return value; + } + + public Type GetClosedParameterType(Type 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)) + { + return parameter.GetGenericTypeDefinition().MakeGenericType(arguments); + } + } + + if (parameter.IsGenericParameter) + { + return GetGenericArgument(parameter.GenericParameterPosition); + } + + 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(int position) + { + Debug.Assert(0 <= position && position < genericTypeParams.Length); + + return genericTypeParams[position]; + } + + public Type[] GetGenericArgumentsFor(MethodInfo genericMethod) + { + Debug.Assert(genericMethod.GetGenericArguments().Length == genericTypeParams.Length); + + return genericTypeParams; + } + + public void SetGenericTypeParameters(GenericTypeParameterBuilder[] genericTypeParameterBuilders) + { + genericTypeParams = genericTypeParameterBuilders; + } + + public Type CreateType(TypeBuilder type) + { + return type.CreateTypeInfo(); + } + + protected void EnsureBuildersAreInAValidState() + { + if (constructors.Count == 0) + { + CreateDefaultConstructor(); + } + + foreach (var builder in properties) + { + builder.Generate(); + } + foreach (var builder in events) + { + builder.Generate(); + } + foreach (var builder in constructors) + { + builder.Generate(); + } + foreach (var builder in methods) + { + builder.Generate(); + } + } } } \ No newline at end of file diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/ConstructorEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/ConstructorEmitter.cs index 98646c1d9d..463da37ace 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/ConstructorEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/ConstructorEmitter.cs @@ -24,16 +24,16 @@ internal class ConstructorEmitter { private readonly ConstructorBuilder builder; private readonly CodeBuilder codeBuilder; - private readonly AbstractTypeEmitter mainType; + private readonly ClassEmitter mainType; - protected internal ConstructorEmitter(AbstractTypeEmitter mainType, ConstructorBuilder builder) + protected internal ConstructorEmitter(ClassEmitter mainType, ConstructorBuilder builder) { this.mainType = mainType; this.builder = builder; codeBuilder = new CodeBuilder(); } - internal ConstructorEmitter(AbstractTypeEmitter mainType, params ArgumentReference[] arguments) + internal ConstructorEmitter(ClassEmitter mainType, params ArgumentReference[] arguments) { this.mainType = mainType; diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/EventEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/EventEmitter.cs index 272f07bcf3..1c48a147b2 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/EventEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/EventEmitter.cs @@ -21,11 +21,11 @@ namespace Castle.DynamicProxy.Generators.Emitters internal class EventEmitter { private readonly EventBuilder eventBuilder; - private readonly AbstractTypeEmitter typeEmitter; + private readonly ClassEmitter typeEmitter; private MethodEmitter addMethod; private MethodEmitter removeMethod; - public EventEmitter(AbstractTypeEmitter typeEmitter, string name, EventAttributes attributes, Type type) + public EventEmitter(ClassEmitter typeEmitter, string name, EventAttributes attributes, Type type) { if (name == null) { diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/MethodEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/MethodEmitter.cs index 1152c93394..b77c62b2de 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/MethodEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/MethodEmitter.cs @@ -40,12 +40,12 @@ protected internal MethodEmitter(MethodBuilder builder) codeBuilder = new CodeBuilder(); } - internal MethodEmitter(AbstractTypeEmitter owner, string name, MethodAttributes attributes) + internal MethodEmitter(ClassEmitter owner, string name, MethodAttributes attributes) : this(owner.TypeBuilder.DefineMethod(name, attributes)) { } - internal MethodEmitter(AbstractTypeEmitter owner, string name, + internal MethodEmitter(ClassEmitter owner, string name, MethodAttributes attributes, Type returnType, params Type[] argumentTypes) : this(owner, name, attributes) @@ -54,7 +54,7 @@ internal MethodEmitter(AbstractTypeEmitter owner, string name, SetReturnType(returnType); } - internal MethodEmitter(AbstractTypeEmitter owner, string name, + internal MethodEmitter(ClassEmitter owner, string name, MethodAttributes attributes, MethodInfo methodToUseAsATemplate) : this(owner, name, attributes) { diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/PropertyEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/PropertyEmitter.cs index 0da52f94b3..0202600dc5 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/PropertyEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/PropertyEmitter.cs @@ -21,11 +21,11 @@ namespace Castle.DynamicProxy.Generators.Emitters internal class PropertyEmitter { private readonly PropertyBuilder builder; - private readonly AbstractTypeEmitter parentTypeEmitter; + private readonly ClassEmitter parentTypeEmitter; private MethodEmitter getMethod; private MethodEmitter setMethod; - public PropertyEmitter(AbstractTypeEmitter parentTypeEmitter, string name, PropertyAttributes attributes, + public PropertyEmitter(ClassEmitter parentTypeEmitter, string name, PropertyAttributes attributes, Type propertyType, Type[] arguments) { this.parentTypeEmitter = parentTypeEmitter; diff --git a/src/Castle.Core/DynamicProxy/Generators/InvocationTypeGenerator.cs b/src/Castle.Core/DynamicProxy/Generators/InvocationTypeGenerator.cs index 749b65e775..4508fc122a 100644 --- a/src/Castle.Core/DynamicProxy/Generators/InvocationTypeGenerator.cs +++ b/src/Castle.Core/DynamicProxy/Generators/InvocationTypeGenerator.cs @@ -24,7 +24,7 @@ namespace Castle.DynamicProxy.Generators using Castle.DynamicProxy.Internal; using Castle.DynamicProxy.Tokens; - internal abstract class InvocationTypeGenerator : IGenerator + internal abstract class InvocationTypeGenerator : IGenerator { protected readonly MetaMethod method; protected readonly Type targetType; @@ -53,7 +53,7 @@ protected abstract ArgumentReference[] GetBaseCtorArguments(Type targetFieldType protected abstract FieldReference GetTargetReference(); - public AbstractTypeEmitter Generate(ClassEmitter @class, INamingScope namingScope) + public ClassEmitter Generate(ClassEmitter @class, INamingScope namingScope) { var methodInfo = method.Method; @@ -86,7 +86,7 @@ public AbstractTypeEmitter Generate(ClassEmitter @class, INamingScope namingScop return invocation; } - protected virtual MethodInvocationExpression GetCallbackMethodInvocation(AbstractTypeEmitter invocation, + protected virtual MethodInvocationExpression GetCallbackMethodInvocation(ClassEmitter invocation, IExpression[] args, MethodInfo callbackMethod, Reference targetField, MethodEmitter invokeMethodOnTarget) @@ -102,7 +102,7 @@ protected virtual MethodInvocationExpression GetCallbackMethodInvocation(Abstrac return methodOnTargetInvocationExpression; } - protected virtual void ImplementInvokeMethodOnTarget(AbstractTypeEmitter invocation, ParameterInfo[] parameters, + protected virtual void ImplementInvokeMethodOnTarget(ClassEmitter invocation, ParameterInfo[] parameters, MethodEmitter invokeMethodOnTarget, Reference targetField) { @@ -268,7 +268,7 @@ private void AssignBackByRefArguments(MethodEmitter invokeMethodOnTarget, Dictio invokeMethodOnTarget.CodeBuilder.AddStatement(new EndExceptionBlockStatement()); } - private void CreateConstructor(AbstractTypeEmitter invocation) + private void CreateConstructor(ClassEmitter invocation) { ConstructorInfo baseConstructor; var baseCtorArguments = GetBaseCtorArguments(targetType, out baseConstructor); @@ -278,7 +278,7 @@ private void CreateConstructor(AbstractTypeEmitter invocation) constructor.CodeBuilder.AddStatement(new ReturnStatement()); } - private ConstructorEmitter CreateConstructor(AbstractTypeEmitter invocation, ArgumentReference[] baseCtorArguments) + private ConstructorEmitter CreateConstructor(ClassEmitter invocation, ArgumentReference[] baseCtorArguments) { if (contributor == null) { @@ -295,7 +295,7 @@ private void EmitCallThrowOnNoTarget(MethodEmitter invokeMethodOnTarget) invokeMethodOnTarget.CodeBuilder.AddStatement(new ReturnStatement()); } - private MethodInfo GetCallbackMethod(AbstractTypeEmitter invocation) + private MethodInfo GetCallbackMethod(ClassEmitter invocation) { if (contributor != null) { @@ -315,23 +315,22 @@ private MethodInfo GetCallbackMethod(AbstractTypeEmitter invocation) return callbackMethod.MakeGenericMethod(invocation.GetGenericArgumentsFor(callbackMethod)); } - private AbstractTypeEmitter GetEmitter(ClassEmitter @class, Type[] interfaces, INamingScope namingScope, - MethodInfo methodInfo) + private ClassEmitter GetEmitter(ClassEmitter @class, Type[] interfaces, INamingScope namingScope, MethodInfo methodInfo) { var suggestedName = string.Format("Castle.Proxies.Invocations.{0}_{1}", methodInfo.DeclaringType.Name, methodInfo.Name); var uniqueName = namingScope.ParentScope.GetUniqueName(suggestedName); - return new ClassEmitter(@class.ModuleScope, uniqueName, GetBaseType(), interfaces, ClassEmitter.DefaultAttributes, forceUnsigned: @class.InStrongNamedModule == false); + return new ClassEmitter(@class.ModuleScope, uniqueName, GetBaseType(), interfaces, ClassEmitter.DefaultTypeAttributes, forceUnsigned: @class.InStrongNamedModule == false); } - private void ImplementInvokeMethodOnTarget(AbstractTypeEmitter invocation, ParameterInfo[] parameters, + private void ImplementInvokeMethodOnTarget(ClassEmitter invocation, ParameterInfo[] parameters, FieldReference targetField, MethodInfo callbackMethod) { var invokeMethodOnTarget = invocation.CreateMethod("InvokeMethodOnTarget", typeof(void)); ImplementInvokeMethodOnTarget(invocation, parameters, invokeMethodOnTarget, targetField); } - private void ImplementChangeInvocationTarget(AbstractTypeEmitter invocation, FieldReference targetField) + private void ImplementChangeInvocationTarget(ClassEmitter invocation, FieldReference targetField) { var changeInvocationTarget = invocation.CreateMethod("ChangeInvocationTarget", typeof(void), new[] { typeof(object) }); changeInvocationTarget.CodeBuilder.AddStatement( @@ -340,7 +339,7 @@ private void ImplementChangeInvocationTarget(AbstractTypeEmitter invocation, Fie changeInvocationTarget.CodeBuilder.AddStatement(new ReturnStatement()); } - private void ImplementChangeProxyTarget(AbstractTypeEmitter invocation, ClassEmitter @class) + private void ImplementChangeProxyTarget(ClassEmitter invocation, ClassEmitter @class) { var changeProxyTarget = invocation.CreateMethod("ChangeProxyTarget", typeof(void), new[] { typeof(object) }); @@ -361,7 +360,7 @@ private void ImplementChangeProxyTarget(AbstractTypeEmitter invocation, ClassEmi changeProxyTarget.CodeBuilder.AddStatement(new ReturnStatement()); } - private void ImplementChangeProxyTargetInterface(ClassEmitter @class, AbstractTypeEmitter invocation, + private void ImplementChangeProxyTargetInterface(ClassEmitter @class, ClassEmitter invocation, FieldReference targetField) { ImplementChangeInvocationTarget(invocation, targetField); From 0efd7a5614992b9fbf0a27ed6189bb28d75eb877 Mon Sep 17 00:00:00 2001 From: Dominique Schuppli Date: Sun, 21 Dec 2025 21:36:54 +0100 Subject: [PATCH 9/9] Merge 2 methods into `ClassEmitter.BuildType` --- .../Generators/Emitters/ClassEmitter.cs | 20 +++++-------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/ClassEmitter.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/ClassEmitter.cs index 8b23dcadc8..151c7ff26b 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/ClassEmitter.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/ClassEmitter.cs @@ -154,15 +154,6 @@ public void AddCustomAttributes(IEnumerable additionalAttri } } - public Type BuildType() - { - EnsureBuildersAreInAValidState(); - - var type = CreateType(typeBuilder); - - return type; - } - public void CopyGenericParametersFromMethod(MethodInfo methodToCopyGenericsFrom) { // big sanity check @@ -387,12 +378,7 @@ public void SetGenericTypeParameters(GenericTypeParameterBuilder[] genericTypePa genericTypeParams = genericTypeParameterBuilders; } - public Type CreateType(TypeBuilder type) - { - return type.CreateTypeInfo(); - } - - protected void EnsureBuildersAreInAValidState() + public Type BuildType() { if (constructors.Count == 0) { @@ -415,6 +401,10 @@ protected void EnsureBuildersAreInAValidState() { builder.Generate(); } + + var type = typeBuilder.CreateTypeInfo(); + + return type; } } } \ No newline at end of file