Skip to content

Commit e52a9da

Browse files
committed
Let ArgumentsMarshaller handle return value, too
1 parent 5a987ec commit e52a9da

1 file changed

Lines changed: 49 additions & 38 deletions

File tree

src/Castle.Core/DynamicProxy/Generators/MethodWithInvocationGenerator.cs

Lines changed: 49 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -139,44 +139,7 @@ protected override MethodEmitter BuildProxiedMethodBody(MethodEmitter emitter, C
139139
emitter.CodeBuilder.AddStatement(EndExceptionBlockStatement.Instance);
140140
}
141141

142-
if (MethodToOverride.ReturnType != typeof(void))
143-
{
144-
IExpression retVal;
145-
146-
#if FEATURE_BYREFLIKE
147-
if (emitter.ReturnType.IsByRefLikeSafe())
148-
{
149-
// The return value in the `ReturnValue` property is an `object`
150-
// and cannot be converted back to the original by-ref-like return type.
151-
// We need to replace it with some other value.
152-
153-
// For now, we just substitute the by-ref-like type's default value:
154-
retVal = new DefaultValueExpression(emitter.ReturnType);
155-
}
156-
else
157-
#endif
158-
{
159-
retVal = new MethodInvocationExpression(invocationLocal, InvocationMethods.GetReturnValue);
160-
161-
// Emit code to ensure a value type return type is not null, otherwise the cast will cause a null-deref
162-
if (emitter.ReturnType.IsValueType && !emitter.ReturnType.IsNullableType())
163-
{
164-
LocalReference returnValue = emitter.CodeBuilder.DeclareLocal(typeof(object));
165-
emitter.CodeBuilder.AddStatement(new AssignStatement(returnValue, retVal));
166-
167-
emitter.CodeBuilder.AddStatement(new IfNullExpression(returnValue, new ThrowStatement(typeof(InvalidOperationException),
168-
"Interceptors failed to set a return value, or swallowed the exception thrown by the target")));
169-
}
170-
171-
retVal = new ConvertExpression(emitter.ReturnType, retVal);
172-
}
173-
174-
emitter.CodeBuilder.AddStatement(new ReturnStatement(retVal));
175-
}
176-
else
177-
{
178-
emitter.CodeBuilder.AddStatement(ReturnStatement.Instance);
179-
}
142+
argumentsMarshaller.Return(invocationLocal);
180143

181144
return emitter;
182145
}
@@ -370,6 +333,54 @@ public void CopyOut(LocalReference argumentsArray)
370333
}
371334
}
372335
}
336+
337+
public void Return(LocalReference invocation)
338+
{
339+
var returnType = method.ReturnType;
340+
341+
if (returnType == typeof(void))
342+
{
343+
method.CodeBuilder.AddStatement(ReturnStatement.Instance);
344+
return;
345+
}
346+
347+
#if FEATURE_BYREFLIKE
348+
if (returnType.IsByRefLikeSafe())
349+
{
350+
// The return value in the `ReturnValue` property is an `object`
351+
// and cannot be converted back to the original by-ref-like return type.
352+
// We need to replace it with some other value.
353+
354+
// For now, we just substitute the by-ref-like type's default value:
355+
method.CodeBuilder.AddStatement(
356+
new ReturnStatement(
357+
new DefaultValueExpression(returnType)));
358+
}
359+
else
360+
#endif
361+
{
362+
var returnValue = method.CodeBuilder.DeclareLocal(typeof(object));
363+
method.CodeBuilder.AddStatement(
364+
new AssignStatement(
365+
returnValue,
366+
new MethodInvocationExpression(invocation, InvocationMethods.GetReturnValue)));
367+
368+
// Emit code to ensure a value type return type is not null, otherwise the cast will cause a null-deref
369+
if (returnType.IsValueType && !returnType.IsNullableType())
370+
{
371+
method.CodeBuilder.AddStatement(
372+
new IfNullExpression(
373+
returnValue,
374+
new ThrowStatement(
375+
typeof(InvalidOperationException),
376+
"Interceptors failed to set a return value, or swallowed the exception thrown by the target")));
377+
}
378+
379+
method.CodeBuilder.AddStatement(
380+
new ReturnStatement(
381+
new ConvertExpression(returnType, returnValue)));
382+
}
383+
}
373384
}
374385
}
375386
}

0 commit comments

Comments
 (0)