diff --git a/src/Castle.Core/DynamicProxy/Contributors/Delegates.cs b/src/Castle.Core/DynamicProxy/Contributors/Delegates.cs index 60a64d617..ffab3c2e3 100644 --- a/src/Castle.Core/DynamicProxy/Contributors/Delegates.cs +++ b/src/Castle.Core/DynamicProxy/Contributors/Delegates.cs @@ -23,6 +23,4 @@ internal delegate MethodEmitter OverrideMethodDelegate( string name, MethodAttributes attributes, MethodInfo methodToOverride); internal delegate IExpression GetTargetExpressionDelegate(ClassEmitter @class, MethodInfo method); - - internal delegate Reference GetTargetReferenceDelegate(ClassEmitter @class, MethodInfo method); } \ No newline at end of file diff --git a/src/Castle.Core/DynamicProxy/Contributors/InterfaceProxyWithOptionalTargetContributor.cs b/src/Castle.Core/DynamicProxy/Contributors/InterfaceProxyWithOptionalTargetContributor.cs index 858a6fb20..26feb983d 100644 --- a/src/Castle.Core/DynamicProxy/Contributors/InterfaceProxyWithOptionalTargetContributor.cs +++ b/src/Castle.Core/DynamicProxy/Contributors/InterfaceProxyWithOptionalTargetContributor.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. @@ -19,13 +19,9 @@ namespace Castle.DynamicProxy.Contributors internal class InterfaceProxyWithOptionalTargetContributor : InterfaceProxyWithoutTargetContributor { - private readonly GetTargetReferenceDelegate getTargetReference; - - public InterfaceProxyWithOptionalTargetContributor(INamingScope namingScope, GetTargetExpressionDelegate getTarget, - GetTargetReferenceDelegate getTargetReference) + public InterfaceProxyWithOptionalTargetContributor(INamingScope namingScope, GetTargetExpressionDelegate getTarget) : base(namingScope, getTarget) { - this.getTargetReference = getTargetReference; canChangeTarget = true; } @@ -34,7 +30,7 @@ protected override MethodGenerator GetMethodGenerator(MetaMethod method, ClassEm { if (!method.Proxyable) { - return new OptionallyForwardingMethodGenerator(method, overrideMethod, getTargetReference); + return new OptionallyForwardingMethodGenerator(method, overrideMethod, getTarget); } return base.GetMethodGenerator(method, @class, overrideMethod); diff --git a/src/Castle.Core/DynamicProxy/Contributors/InterfaceProxyWithoutTargetContributor.cs b/src/Castle.Core/DynamicProxy/Contributors/InterfaceProxyWithoutTargetContributor.cs index aa465956d..d3eca51ad 100644 --- a/src/Castle.Core/DynamicProxy/Contributors/InterfaceProxyWithoutTargetContributor.cs +++ b/src/Castle.Core/DynamicProxy/Contributors/InterfaceProxyWithoutTargetContributor.cs @@ -26,13 +26,13 @@ namespace Castle.DynamicProxy.Contributors internal class InterfaceProxyWithoutTargetContributor : CompositeTypeContributor { - private readonly GetTargetExpressionDelegate getTargetExpression; + protected readonly GetTargetExpressionDelegate getTarget; protected bool canChangeTarget = false; public InterfaceProxyWithoutTargetContributor(INamingScope namingScope, GetTargetExpressionDelegate getTarget) : base(namingScope) { - getTargetExpression = getTarget; + this.getTarget = getTarget; } protected override IEnumerable GetCollectors() @@ -56,7 +56,7 @@ protected override MethodGenerator GetMethodGenerator(MetaMethod method, ClassEm return new MethodWithInvocationGenerator(method, @class.GetField("__interceptors"), invocation, - getTargetExpression, + getTarget, overrideMethod, null); } diff --git a/src/Castle.Core/DynamicProxy/Contributors/MixinContributor.cs b/src/Castle.Core/DynamicProxy/Contributors/MixinContributor.cs index e6070994e..9f63b269b 100644 --- a/src/Castle.Core/DynamicProxy/Contributors/MixinContributor.cs +++ b/src/Castle.Core/DynamicProxy/Contributors/MixinContributor.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. @@ -114,7 +114,7 @@ private GetTargetExpressionDelegate BuildGetTargetExpression() } return (c, m) => new NullCoalescingOperatorExpression( - new AsTypeReference(c.GetField("__target"), m.DeclaringType), + new AsTypeExpression(c.GetField("__target"), m.DeclaringType), fields[m.DeclaringType]); } diff --git a/src/Castle.Core/DynamicProxy/Contributors/SerializableContributor.cs b/src/Castle.Core/DynamicProxy/Contributors/SerializableContributor.cs index c4ff33945..d1b54f599 100644 --- a/src/Castle.Core/DynamicProxy/Contributors/SerializableContributor.cs +++ b/src/Castle.Core/DynamicProxy/Contributors/SerializableContributor.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. @@ -90,9 +90,8 @@ protected void ImplementGetObjectData(ClassEmitter emitter) for (var i = 0; i < interfaces.Length; i++) { getObjectData.CodeBuilder.AddStatement( - new AssignArrayStatement( - interfacesLocal, - i, + new AssignStatement( + new ArrayElementReference(interfacesLocal, i), new LiteralStringExpression(interfaces[i].AssemblyQualifiedName))); } diff --git a/src/Castle.Core/DynamicProxy/Generators/BaseProxyGenerator.cs b/src/Castle.Core/DynamicProxy/Generators/BaseProxyGenerator.cs index 2d790409d..ec1a150ac 100644 --- a/src/Castle.Core/DynamicProxy/Generators/BaseProxyGenerator.cs +++ b/src/Castle.Core/DynamicProxy/Generators/BaseProxyGenerator.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. @@ -331,7 +331,9 @@ protected void GenerateParameterlessConstructor(ClassEmitter emitter, Type baseC constructor.CodeBuilder.AddStatement(new AssignStatement(interceptorField, new NewArrayExpression(1, typeof(IInterceptor)))); constructor.CodeBuilder.AddStatement( - new AssignArrayStatement(interceptorField, 0, new NewInstanceExpression(typeof(StandardInterceptor)))); + new AssignStatement( + new ArrayElementReference(interceptorField, 0), + new NewInstanceExpression(typeof(StandardInterceptor)))); // Invoke base constructor diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/SimpleAST/LoadRefArrayElementExpression.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/SimpleAST/AddressOfExpression.cs similarity index 66% rename from src/Castle.Core/DynamicProxy/Generators/Emitters/SimpleAST/LoadRefArrayElementExpression.cs rename to src/Castle.Core/DynamicProxy/Generators/Emitters/SimpleAST/AddressOfExpression.cs index d6db83640..60345f173 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/SimpleAST/LoadRefArrayElementExpression.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/SimpleAST/AddressOfExpression.cs @@ -16,24 +16,22 @@ namespace Castle.DynamicProxy.Generators.Emitters.SimpleAST { + using System.Diagnostics; using System.Reflection.Emit; - internal class LoadRefArrayElementExpression : IExpression + [DebuggerDisplay("&{reference}")] + internal class AddressOfExpression : IExpression { - private readonly Reference arrayReference; - private readonly LiteralIntExpression index; + private readonly Reference reference; - public LoadRefArrayElementExpression(int index, Reference arrayReference) + public AddressOfExpression(Reference reference) { - this.index = new LiteralIntExpression(index); - this.arrayReference = arrayReference; + this.reference = reference; } public void Emit(ILGenerator gen) { - arrayReference.Emit(gen); - index.Emit(gen); - gen.Emit(OpCodes.Ldelem_Ref); + reference.EmitAddress(gen); } } } \ No newline at end of file diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/SimpleAST/ArrayElementReference.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/SimpleAST/ArrayElementReference.cs new file mode 100644 index 000000000..bb9241a30 --- /dev/null +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/SimpleAST/ArrayElementReference.cs @@ -0,0 +1,64 @@ +// 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. + +#nullable enable + +namespace Castle.DynamicProxy.Generators.Emitters.SimpleAST +{ + using System.Diagnostics; + using System.Reflection.Emit; + + internal sealed class ArrayElementReference : Reference + { + private readonly Reference array; + private readonly int index; + + public ArrayElementReference(Reference array, int index) + : base(array.Type.GetElementType()!) + { + Debug.Assert(array.Type.IsArray); + + // The below methods have the `ldelem.ref` and `stelem.ref` opcodes hardcoded, + // which is only correct for reference types. Once we start using this class + // for arrays of primitive types, enums, value types, or generic parameters, + // we will need to revisit this. + Debug.Assert(array.Type.GetElementType()!.IsClass || array.Type.GetElementType()!.IsInterface); + + this.array = array; + this.index = index; + } + + public override void Emit(ILGenerator gen) + { + array.Emit(gen); + gen.Emit(OpCodes.Ldc_I4, index); + gen.Emit(OpCodes.Ldelem_Ref); + } + + public override void EmitAddress(ILGenerator gen) + { + array.Emit(gen); + gen.Emit(OpCodes.Ldc_I4, index); + gen.Emit(OpCodes.Ldelema); + } + + public override void EmitStore(IExpression value, ILGenerator gen) + { + array.Emit(gen); + gen.Emit(OpCodes.Ldc_I4, index); + value.Emit(gen); + gen.Emit(OpCodes.Stelem_Ref); + } + } +} diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/SimpleAST/AsTypeReference.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/SimpleAST/AsTypeExpression.cs similarity index 59% rename from src/Castle.Core/DynamicProxy/Generators/Emitters/SimpleAST/AsTypeReference.cs rename to src/Castle.Core/DynamicProxy/Generators/Emitters/SimpleAST/AsTypeExpression.cs index 58d7866f7..003e83d65 100644 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/SimpleAST/AsTypeReference.cs +++ b/src/Castle.Core/DynamicProxy/Generators/Emitters/SimpleAST/AsTypeExpression.cs @@ -21,36 +21,21 @@ namespace Castle.DynamicProxy.Generators.Emitters.SimpleAST using System.Reflection.Emit; [DebuggerDisplay("{reference} as {type}")] - internal class AsTypeReference : Reference + internal class AsTypeExpression : IExpression { private readonly Reference reference; private readonly Type type; - public AsTypeReference(Reference reference, Type type) - : base(type) + public AsTypeExpression(Reference reference, Type type) { this.reference = reference; this.type = type; } - public override void EmitAddress(ILGenerator gen) - { - // It does not make sense to take the address of a cast expression. - // The C# language would also forbid address-taking of the form `&(x as T)`. - throw new NotSupportedException(); - } - - public override void Emit(ILGenerator gen) + public void Emit(ILGenerator gen) { reference.Emit(gen); gen.Emit(OpCodes.Isinst, type); } - - public override void EmitStore(IExpression value, ILGenerator gen) - { - // It does not make sense to assign a value to the result of a cast expression. - // The C# language would also forbid assignments of the form `(x as T) = y`. - throw new NotSupportedException(); - } } } \ No newline at end of file diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/SimpleAST/AssignArrayStatement.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/SimpleAST/AssignArrayStatement.cs deleted file mode 100644 index d02432c48..000000000 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/SimpleAST/AssignArrayStatement.cs +++ /dev/null @@ -1,45 +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. - -#nullable enable - -namespace Castle.DynamicProxy.Generators.Emitters.SimpleAST -{ - using System.Reflection.Emit; - - internal class AssignArrayStatement : IStatement - { - private readonly Reference targetArray; - private readonly int targetPosition; - private readonly IExpression value; - - public AssignArrayStatement(Reference targetArray, int targetPosition, IExpression value) - { - this.targetArray = targetArray; - this.targetPosition = targetPosition; - this.value = value; - } - - public void Emit(ILGenerator il) - { - targetArray.Emit(il); - - il.Emit(OpCodes.Ldc_I4, targetPosition); - - value.Emit(il); - - il.Emit(OpCodes.Stelem_Ref); - } - } -} \ No newline at end of file diff --git a/src/Castle.Core/DynamicProxy/Generators/Emitters/SimpleAST/ByRefReference.cs b/src/Castle.Core/DynamicProxy/Generators/Emitters/SimpleAST/ByRefReference.cs deleted file mode 100644 index 769e97db5..000000000 --- a/src/Castle.Core/DynamicProxy/Generators/Emitters/SimpleAST/ByRefReference.cs +++ /dev/null @@ -1,50 +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. - -#nullable enable - -namespace Castle.DynamicProxy.Generators.Emitters.SimpleAST -{ - using System; - using System.Diagnostics; - using System.Reflection.Emit; - - - [DebuggerDisplay("&{localReference}")] - internal class ByRefReference : Reference - { - private readonly LocalReference localReference; - - public ByRefReference(LocalReference localReference) - : base(localReference.Type) - { - this.localReference = localReference; - } - - public override void EmitAddress(ILGenerator gen) - { - localReference.EmitAddress(gen); - } - - public override void Emit(ILGenerator gen) - { - localReference.EmitAddress(gen); - } - - public override void EmitStore(IExpression value, ILGenerator gen) - { - throw new NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/src/Castle.Core/DynamicProxy/Generators/ForwardingMethodGenerator.cs b/src/Castle.Core/DynamicProxy/Generators/ForwardingMethodGenerator.cs index 6b7364f6e..769b0cffe 100644 --- a/src/Castle.Core/DynamicProxy/Generators/ForwardingMethodGenerator.cs +++ b/src/Castle.Core/DynamicProxy/Generators/ForwardingMethodGenerator.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,24 +20,24 @@ namespace Castle.DynamicProxy.Generators internal class ForwardingMethodGenerator : MethodGenerator { - private readonly GetTargetReferenceDelegate getTargetReference; + private readonly GetTargetExpressionDelegate getTarget; public ForwardingMethodGenerator(MetaMethod method, OverrideMethodDelegate overrideMethod, - GetTargetReferenceDelegate getTargetReference) + GetTargetExpressionDelegate getTarget) : base(method, overrideMethod) { - this.getTargetReference = getTargetReference; + this.getTarget = getTarget; } protected override MethodEmitter BuildProxiedMethodBody(MethodEmitter emitter, ClassEmitter @class, INamingScope namingScope) { - var targetReference = getTargetReference(@class, MethodToOverride); + var target = getTarget(@class, MethodToOverride); var arguments = ArgumentsUtil.ConvertToArgumentReferenceExpression(MethodToOverride.GetParameters()); emitter.CodeBuilder.AddStatement(new ReturnStatement( new MethodInvocationExpression( - targetReference, + target, MethodToOverride, arguments) { VirtualCall = true })); return emitter; diff --git a/src/Castle.Core/DynamicProxy/Generators/GeneratorUtil.cs b/src/Castle.Core/DynamicProxy/Generators/GeneratorUtil.cs index de8245877..9ece9992b 100644 --- a/src/Castle.Core/DynamicProxy/Generators/GeneratorUtil.cs +++ b/src/Castle.Core/DynamicProxy/Generators/GeneratorUtil.cs @@ -133,7 +133,7 @@ bool IsReadOnly(ParameterInfo parameter) private static ConvertExpression Argument(int i, LocalReference invocationArgs, Reference[] arguments) { - return new ConvertExpression(arguments[i].Type, new LoadRefArrayElementExpression(i, invocationArgs)); + return new ConvertExpression(arguments[i].Type, new ArrayElementReference(invocationArgs, i)); } private static AssignStatement AssignArgument(Reference[] dereferencedArguments, int i, diff --git a/src/Castle.Core/DynamicProxy/Generators/InterfaceProxyWithTargetInterfaceGenerator.cs b/src/Castle.Core/DynamicProxy/Generators/InterfaceProxyWithTargetInterfaceGenerator.cs index f0f6d2a2b..47106c7bf 100644 --- a/src/Castle.Core/DynamicProxy/Generators/InterfaceProxyWithTargetInterfaceGenerator.cs +++ b/src/Castle.Core/DynamicProxy/Generators/InterfaceProxyWithTargetInterfaceGenerator.cs @@ -57,18 +57,13 @@ protected override void AddMappingForAdditionalInterfaces(CompositeTypeContribut protected override InterfaceProxyWithoutTargetContributor GetContributorForAdditionalInterfaces( INamingScope namingScope) { - return new InterfaceProxyWithOptionalTargetContributor(namingScope, GetTargetExpression, GetTarget) + return new InterfaceProxyWithOptionalTargetContributor(namingScope, GetTarget) { Logger = Logger }; } - private Reference GetTarget(ClassEmitter @class, MethodInfo method) + private IExpression GetTarget(ClassEmitter @class, MethodInfo method) { - return new AsTypeReference(@class.GetField("__target"), method.DeclaringType); - } - - private IExpression GetTargetExpression(ClassEmitter @class, MethodInfo method) - { - return GetTarget(@class, method); + return new AsTypeExpression(@class.GetField("__target"), method.DeclaringType); } } } \ No newline at end of file diff --git a/src/Castle.Core/DynamicProxy/Generators/InvocationTypeGenerator.cs b/src/Castle.Core/DynamicProxy/Generators/InvocationTypeGenerator.cs index b0c2a13b0..749b65e77 100644 --- a/src/Castle.Core/DynamicProxy/Generators/InvocationTypeGenerator.cs +++ b/src/Castle.Core/DynamicProxy/Generators/InvocationTypeGenerator.cs @@ -96,7 +96,7 @@ protected virtual MethodInvocationExpression GetCallbackMethodInvocation(Abstrac return contributor.GetCallbackMethodInvocation(invocation, args, targetField, invokeMethodOnTarget); } var methodOnTargetInvocationExpression = new MethodInvocationExpression( - new AsTypeReference(targetField, callbackMethod.DeclaringType), + new AsTypeExpression(targetField, callbackMethod.DeclaringType), callbackMethod, args) { VirtualCall = true }; return methodOnTargetInvocationExpression; @@ -149,8 +149,8 @@ protected virtual void ImplementInvokeMethodOnTarget(AbstractTypeEmitter invocat } invokeMethodOnTarget.CodeBuilder.AddStatement(new AssignStatement(localReference, localValue)); - var byRefReference = new ByRefReference(localReference); - args[i] = byRefReference; + var localByRef = new AddressOfExpression(localReference); + args[i] = localByRef; byRefArguments[i] = localReference; } else diff --git a/src/Castle.Core/DynamicProxy/Generators/MethodWithInvocationGenerator.cs b/src/Castle.Core/DynamicProxy/Generators/MethodWithInvocationGenerator.cs index 765355b52..8f1e1ead6 100644 --- a/src/Castle.Core/DynamicProxy/Generators/MethodWithInvocationGenerator.cs +++ b/src/Castle.Core/DynamicProxy/Generators/MethodWithInvocationGenerator.cs @@ -222,7 +222,9 @@ private void EmitLoadGenericMethodArguments(MethodEmitter methodEmitter, MethodI for (var i = 0; i < genericParameters.Length; ++i) { methodEmitter.CodeBuilder.AddStatement( - new AssignArrayStatement(genericParamsArrayLocal, i, new TypeTokenExpression(genericParameters[i]))); + new AssignStatement( + new ArrayElementReference(genericParamsArrayLocal, i), + new TypeTokenExpression(genericParameters[i]))); } methodEmitter.CodeBuilder.AddStatement( new MethodInvocationExpression(invocationLocal, diff --git a/src/Castle.Core/DynamicProxy/Generators/OptionallyForwardingMethodGenerator.cs b/src/Castle.Core/DynamicProxy/Generators/OptionallyForwardingMethodGenerator.cs index 51a36f2f7..9ae81f7d2 100644 --- a/src/Castle.Core/DynamicProxy/Generators/OptionallyForwardingMethodGenerator.cs +++ b/src/Castle.Core/DynamicProxy/Generators/OptionallyForwardingMethodGenerator.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. @@ -24,37 +24,37 @@ namespace Castle.DynamicProxy.Generators internal class OptionallyForwardingMethodGenerator : MethodGenerator { // TODO: This class largely duplicates code from Forwarding and Minimalistic generators. Should be refactored to change that - private readonly GetTargetReferenceDelegate getTargetReference; + private readonly GetTargetExpressionDelegate getTarget; public OptionallyForwardingMethodGenerator(MetaMethod method, OverrideMethodDelegate overrideMethod, - GetTargetReferenceDelegate getTargetReference) + GetTargetExpressionDelegate getTarget) : base(method, overrideMethod) { - this.getTargetReference = getTargetReference; + this.getTarget = getTarget; } protected override MethodEmitter BuildProxiedMethodBody(MethodEmitter emitter, ClassEmitter @class, INamingScope namingScope) { - var targetReference = getTargetReference(@class, MethodToOverride); + var target = getTarget(@class, MethodToOverride); emitter.CodeBuilder.AddStatement( new IfNullExpression( - targetReference, + target, IfNull(emitter.ReturnType), - IfNotNull(targetReference))); + IfNotNull(target))); return emitter; } - private IStatement IfNotNull(Reference targetReference) + private IStatement IfNotNull(IExpression target) { var statements = new BlockStatement(); var arguments = ArgumentsUtil.ConvertToArgumentReferenceExpression(MethodToOverride.GetParameters()); statements.AddStatement(new ReturnStatement( new MethodInvocationExpression( - targetReference, + target, MethodToOverride, arguments) { VirtualCall = true })); return statements;