Skip to content

Commit eed779d

Browse files
committed
Introduce ConvertArgumentFromObjectExpression
... as the counterpart to `ConvertArgumentToObjectExpression`. For now, this is just a simplified version of `ConvertExpression`, but it gives us a place to add arguments-specific marshalling logic later on.
1 parent e52a9da commit eed779d

2 files changed

Lines changed: 81 additions & 4 deletions

File tree

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Copyright 2004-2026 Castle Project - http://www.castleproject.org/
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
namespace Castle.DynamicProxy.Generators.Emitters.SimpleAST
16+
{
17+
using System;
18+
using System.Diagnostics;
19+
using System.Reflection.Emit;
20+
21+
internal class ConvertArgumentFromObjectExpression : IExpression
22+
{
23+
private readonly IExpression obj;
24+
private Type dereferencedArgumentType;
25+
26+
public ConvertArgumentFromObjectExpression(Reference obj, Type dereferencedArgumentType)
27+
{
28+
Debug.Assert(obj.Type == typeof(object));
29+
Debug.Assert(dereferencedArgumentType.IsByRef == false);
30+
31+
this.obj = obj;
32+
this.dereferencedArgumentType = dereferencedArgumentType;
33+
}
34+
35+
public void Emit(ILGenerator gen)
36+
{
37+
obj.Emit(gen);
38+
39+
if (dereferencedArgumentType == typeof(object))
40+
{
41+
return;
42+
}
43+
44+
if (dereferencedArgumentType.IsValueType)
45+
{
46+
// Unbox conversion
47+
// Assumes fromType is a boxed value
48+
// if we can, we emit a box and ldind, otherwise, we will use unbox.any
49+
if (LdindOpCodesDictionary.Instance[dereferencedArgumentType] != LdindOpCodesDictionary.EmptyOpCode)
50+
{
51+
gen.Emit(OpCodes.Unbox, dereferencedArgumentType);
52+
OpCodeUtil.EmitLoadIndirectOpCodeForType(gen, dereferencedArgumentType);
53+
}
54+
else
55+
{
56+
gen.Emit(OpCodes.Unbox_Any, dereferencedArgumentType);
57+
}
58+
}
59+
else
60+
{
61+
// Possible down-cast
62+
if (dereferencedArgumentType.IsGenericParameter)
63+
{
64+
gen.Emit(OpCodes.Unbox_Any, dereferencedArgumentType);
65+
}
66+
else if (dereferencedArgumentType.IsGenericType)
67+
{
68+
gen.Emit(OpCodes.Castclass, dereferencedArgumentType);
69+
}
70+
else if (dereferencedArgumentType.IsSubclassOf(typeof(object)))
71+
{
72+
gen.Emit(OpCodes.Castclass, dereferencedArgumentType);
73+
}
74+
}
75+
}
76+
}
77+
}

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -326,9 +326,9 @@ public void CopyOut(LocalReference argumentsArray)
326326
method.CodeBuilder.AddStatement(
327327
new AssignStatement(
328328
dereferencedArgument,
329-
new ConvertExpression(
330-
dereferencedArgumentType,
331-
new ArrayElementReference(argumentsArray, i))));
329+
new ConvertArgumentFromObjectExpression(
330+
new ArrayElementReference(argumentsArray, i),
331+
dereferencedArgumentType)));
332332
}
333333
}
334334
}
@@ -378,7 +378,7 @@ public void Return(LocalReference invocation)
378378

379379
method.CodeBuilder.AddStatement(
380380
new ReturnStatement(
381-
new ConvertExpression(returnType, returnValue)));
381+
new ConvertArgumentFromObjectExpression(returnValue, returnType)));
382382
}
383383
}
384384
}

0 commit comments

Comments
 (0)