Skip to content

Commit f0ad4ce

Browse files
nivalxerliuhaoyang
andauthored
fix intercept method with out decimal error (#255)
* fix intercept method with out decimal error Signed-off-by: nivalxer <[email protected]> * 还原EmitLoadArg Co-authored-by: liuhaoyang <[email protected]>
1 parent a71e603 commit f0ad4ce

File tree

8 files changed

+206
-93
lines changed

8 files changed

+206
-93
lines changed

src/AspectCore.Core/Utils/ProxyGeneratorUtils.cs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -569,12 +569,14 @@ void EmitMethodBody()
569569
{
570570
if (parameters[i].IsByRef)
571571
{
572+
Type byrefToType = parameters[i].GetElementType();
573+
572574
ilGen.EmitLoadArg(i + 1);
573575
ilGen.Emit(OpCodes.Ldloc, argsLocal);
574576
ilGen.EmitInt(i);
575577
ilGen.Emit(OpCodes.Ldelem_Ref);
576578
ilGen.EmitConvertFromObject(parameters[i].GetElementType());
577-
ilGen.EmitStRef(parameters[i]);
579+
ilGen.EmitStRef(byrefToType);
578580
}
579581
}
580582
if (!method.IsVoid())
@@ -622,12 +624,14 @@ void EmitProxyMethodBody()
622624
{
623625
if (parameterTypes[i].IsByRef)
624626
{
627+
Type byrefToType = parameterTypes[i].GetElementType();
628+
625629
ilGen.EmitLoadArg(i + 1);
626630
ilGen.Emit(OpCodes.Ldloc, parameters);
627631
ilGen.EmitInt(i);
628632
ilGen.Emit(OpCodes.Ldelem_Ref);
629-
ilGen.EmitConvertFromObject(parameterTypes[i].GetElementType());
630-
ilGen.EmitStRef(parameterTypes[i]);
633+
ilGen.EmitConvertFromObject(byrefToType);
634+
ilGen.EmitStRef(byrefToType);
631635
}
632636
}
633637
}
@@ -928,7 +932,7 @@ private static void CopyDefaultValueConstant(ParameterInfo from, ParameterBuilde
928932
// If this bug is present, it is caused by a `null` default value:
929933
defaultValue = null;
930934
}
931-
catch (FormatException) when (from.ParameterType.GetTypeInfo().IsEnum)
935+
catch (FormatException) when (from.ParameterType.IsEnum)
932936
{
933937
// This catch clause guards against a CLR bug that makes it impossible to query
934938
// the default value of a (closed generic) enum parameter. For the CoreCLR, see
@@ -973,7 +977,7 @@ private static void CopyDefaultValueConstant(ParameterInfo from, ParameterBuilde
973977
// would "produce" a default value of `Missing.Value` in this situation).
974978
return;
975979
}
976-
else if (parameterType.GetTypeInfo().IsValueType)
980+
else if (parameterType.IsValueType)
977981
{
978982
// This guards against a CLR bug that prohibits replicating `null` default
979983
// values for non-nullable value types (which, despite the apparent type
@@ -989,7 +993,7 @@ private static void CopyDefaultValueConstant(ParameterInfo from, ParameterBuilde
989993
else if (isNullableType)
990994
{
991995
parameterNonNullableType = from.ParameterType.GetGenericArguments()[0];
992-
if (parameterNonNullableType.GetTypeInfo().IsEnum || parameterNonNullableType.IsInstanceOfType(defaultValue))
996+
if (parameterNonNullableType.IsEnum || parameterNonNullableType.IsInstanceOfType(defaultValue))
993997
{
994998
// This guards against two bugs:
995999
//

src/AspectCore.Extensions.Reflection/Emit/ILGeneratorExtensions.cs

Lines changed: 81 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -210,25 +210,17 @@ public static void EmitCastToType(this ILGenerator ilGenerator, TypeInfo typeFro
210210
{
211211
throw new ArgumentNullException(nameof(ilGenerator));
212212
}
213-
if (!typeFrom.IsValueType && typeTo.IsValueType)
213+
if (typeFrom.IsValueType)
214214
{
215-
ilGenerator.Emit(OpCodes.Unbox_Any, typeTo.AsType());
216-
}
217-
else if (typeFrom.IsValueType && !typeTo.IsValueType)
218-
{
219-
ilGenerator.Emit(OpCodes.Box, typeFrom.AsType());
220-
if (typeTo.AsType() != typeof(object))
215+
ilGenerator.Emit(OpCodes.Box, typeFrom);
216+
if (typeTo != typeof(object))
221217
{
222-
ilGenerator.Emit(OpCodes.Castclass, typeTo.AsType());
218+
ilGenerator.Emit(OpCodes.Castclass, typeTo);
223219
}
224220
}
225-
else if (!typeFrom.IsValueType && !typeTo.IsValueType)
226-
{
227-
ilGenerator.Emit(OpCodes.Castclass, typeTo.AsType());
228-
}
229221
else
230222
{
231-
throw new InvalidCastException($"Caanot cast {typeFrom} to {typeTo}.");
223+
ilGenerator.Emit(typeTo.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass, typeTo);
232224
}
233225
}
234226

@@ -693,49 +685,48 @@ public static void EmitLdRef(this ILGenerator ilGenerator, Type type)
693685
{
694686
throw new ArgumentNullException(nameof(type));
695687
}
696-
if (type == typeof(short))
697-
{
698-
ilGenerator.Emit(OpCodes.Ldind_I1);
699-
}
700-
else if (type == typeof(Int16))
701-
{
702-
ilGenerator.Emit(OpCodes.Ldind_I2);
703-
}
704-
else if (type == typeof(Int32))
705-
{
706-
ilGenerator.Emit(OpCodes.Ldind_I4);
707-
}
708-
else if (type == typeof(Int64))
709-
{
710-
ilGenerator.Emit(OpCodes.Ldind_I8);
711-
}
712-
else if (type == typeof(float))
713-
{
714-
ilGenerator.Emit(OpCodes.Ldind_R4);
715-
}
716-
else if (type == typeof(double))
717-
{
718-
ilGenerator.Emit(OpCodes.Ldind_R8);
719-
}
720-
else if (type == typeof(ushort))
721-
{
722-
ilGenerator.Emit(OpCodes.Ldind_U1);
723-
}
724-
else if (type == typeof(UInt16))
725-
{
726-
ilGenerator.Emit(OpCodes.Ldind_U2);
727-
}
728-
else if (type == typeof(UInt32))
729-
{
730-
ilGenerator.Emit(OpCodes.Ldind_U4);
731-
}
732-
else if (type.GetTypeInfo().IsValueType)
733-
{
734-
ilGenerator.Emit(OpCodes.Ldobj);
735-
}
736-
else
688+
switch (Type.GetTypeCode(type))
737689
{
738-
ilGenerator.Emit(OpCodes.Ldind_Ref);
690+
case TypeCode.SByte:
691+
ilGenerator.Emit(OpCodes.Ldind_I1);
692+
break;
693+
case TypeCode.Boolean:
694+
case TypeCode.Byte:
695+
ilGenerator.Emit(OpCodes.Ldind_U1);
696+
break;
697+
case TypeCode.Int16:
698+
ilGenerator.Emit(OpCodes.Ldind_I2);
699+
break;
700+
case TypeCode.Char:
701+
case TypeCode.UInt16:
702+
ilGenerator.Emit(OpCodes.Ldind_U2);
703+
break;
704+
case TypeCode.Int32:
705+
ilGenerator.Emit(OpCodes.Ldind_I4);
706+
break;
707+
case TypeCode.UInt32:
708+
ilGenerator.Emit(OpCodes.Ldind_U4);
709+
break;
710+
case TypeCode.Int64:
711+
case TypeCode.UInt64:
712+
ilGenerator.Emit(OpCodes.Ldind_I8);
713+
break;
714+
case TypeCode.Single:
715+
ilGenerator.Emit(OpCodes.Ldind_R4);
716+
break;
717+
case TypeCode.Double:
718+
ilGenerator.Emit(OpCodes.Ldind_R8);
719+
break;
720+
default:
721+
if (type.IsValueType)
722+
{
723+
ilGenerator.Emit(OpCodes.Ldobj, type);
724+
}
725+
else
726+
{
727+
ilGenerator.Emit(OpCodes.Ldind_Ref);
728+
}
729+
break;
739730
}
740731
}
741732

@@ -749,37 +740,42 @@ public static void EmitStRef(this ILGenerator ilGenerator, Type type)
749740
{
750741
throw new ArgumentNullException(nameof(type));
751742
}
752-
if (type == typeof(short))
753-
{
754-
ilGenerator.Emit(OpCodes.Stind_I1);
755-
}
756-
else if (type == typeof(Int16))
757-
{
758-
ilGenerator.Emit(OpCodes.Stind_I2);
759-
}
760-
else if (type == typeof(Int32))
761-
{
762-
ilGenerator.Emit(OpCodes.Stind_I4);
763-
}
764-
else if (type == typeof(Int64))
765-
{
766-
ilGenerator.Emit(OpCodes.Stind_I8);
767-
}
768-
else if (type == typeof(float))
769-
{
770-
ilGenerator.Emit(OpCodes.Stind_R4);
771-
}
772-
else if (type == typeof(double))
773-
{
774-
ilGenerator.Emit(OpCodes.Stind_R8);
775-
}
776-
else if (type.GetTypeInfo().IsValueType)
777-
{
778-
ilGenerator.Emit(OpCodes.Stobj);
779-
}
780-
else
743+
switch (Type.GetTypeCode(type))
781744
{
782-
ilGenerator.Emit(OpCodes.Stind_Ref);
745+
case TypeCode.Boolean:
746+
case TypeCode.Byte:
747+
case TypeCode.SByte:
748+
ilGenerator.Emit(OpCodes.Stind_I1);
749+
break;
750+
case TypeCode.Char:
751+
case TypeCode.Int16:
752+
case TypeCode.UInt16:
753+
ilGenerator.Emit(OpCodes.Stind_I2);
754+
break;
755+
case TypeCode.Int32:
756+
case TypeCode.UInt32:
757+
ilGenerator.Emit(OpCodes.Stind_I4);
758+
break;
759+
case TypeCode.Int64:
760+
case TypeCode.UInt64:
761+
ilGenerator.Emit(OpCodes.Stind_I8);
762+
break;
763+
case TypeCode.Single:
764+
ilGenerator.Emit(OpCodes.Stind_R4);
765+
break;
766+
case TypeCode.Double:
767+
ilGenerator.Emit(OpCodes.Stind_R8);
768+
break;
769+
default:
770+
if (type.IsValueType)
771+
{
772+
ilGenerator.Emit(OpCodes.Stobj, type);
773+
}
774+
else
775+
{
776+
ilGenerator.Emit(OpCodes.Stind_Ref);
777+
}
778+
break;
783779
}
784780
}
785781

tests/AspectCore.Extensions.Autofac.Test/AspectCore.Extensions.Autofac.Test.csproj

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@
2727
</PackageReference>
2828
<PackageReference Include="System.Runtime.Serialization.Primitives" Version="4.3.0" />
2929
<PackageReference Include="xunit" Version="2.4.1" />
30-
<PackageReference Include="System.Reflection" Version="4.3.0" />
31-
<PackageReference Include="System.Linq" Version="4.3.0" />
3230
</ItemGroup>
3331

3432
</Project>
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using System.Globalization;
2+
using System.Threading.Tasks;
3+
using AspectCore.DynamicProxy;
4+
5+
namespace AspectCore.Extensions.Test.Fakes
6+
{
7+
public class FakeServiceWithOutInterceptor : AbstractInterceptorAttribute
8+
{
9+
public override async Task Invoke(AspectContext context, AspectDelegate next)
10+
{
11+
await next(context);
12+
}
13+
}
14+
15+
[FakeServiceWithOutInterceptor]
16+
public interface IFakeServiceWithOut
17+
{
18+
bool OutDecimal(out decimal num);
19+
20+
bool OutInt(out int num);
21+
}
22+
23+
public class FakeServiceWithOut : IFakeServiceWithOut
24+
{
25+
public bool OutDecimal(out decimal num)
26+
{
27+
num = 1.0M;
28+
return true;
29+
}
30+
31+
public bool OutInt(out int num)
32+
{
33+
num = 1;
34+
return true;
35+
}
36+
}
37+
}

tests/AspectCore.Extensions.Autofac.Test/RegistrationExtensionsTests.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.Reflection;
22
using AspectCore.Configuration;
3+
using AspectCore.DependencyInjection;
34
using AspectCore.DynamicProxy;
45
using AspectCore.Extensions.Autofac;
56
using AspectCore.Extensions.Test.Fakes;
@@ -67,5 +68,31 @@ public void AsProxyWithParamter_Test()
6768
var proxyController = container.Resolve<IController>();
6869
Assert.Equal(proxyService.Get(100), proxyController.Execute());
6970
}
71+
72+
[Fact]
73+
public void Intercept_OutWithDecimalParamter_Test()
74+
{
75+
var builder = CreateBuilder();
76+
builder.RegisterType<FakeServiceWithOut>().As<IFakeServiceWithOut>();
77+
var container = builder.Build();
78+
79+
var proxyServiceWithOut = container.Resolve<IFakeServiceWithOut>();
80+
decimal num;
81+
Assert.True(proxyServiceWithOut.OutDecimal(out num));
82+
Assert.Equal(1.0M, num);
83+
}
84+
85+
[Fact]
86+
public void Intercept_OutWithIntParamter_Test()
87+
{
88+
var builder = CreateBuilder();
89+
builder.RegisterType<FakeServiceWithOut>().As<IFakeServiceWithOut>();
90+
var container = builder.Build();
91+
92+
var proxyServiceWithOut = container.Resolve<IFakeServiceWithOut>();
93+
int num;
94+
Assert.True(proxyServiceWithOut.OutInt(out num));
95+
Assert.Equal(1, num);
96+
}
7097
}
7198
}

tests/AspectCore.Tests/Classes.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,4 +243,35 @@ string IFakeExplicitImplementation.GetVal_NonAspect()
243243
return "lemon";
244244
}
245245
}
246+
247+
public class FakeServiceWithOutInterceptor : AbstractInterceptorAttribute
248+
{
249+
public override async Task Invoke(AspectContext context, AspectDelegate next)
250+
{
251+
await next(context);
252+
}
253+
}
254+
255+
[FakeServiceWithOutInterceptor]
256+
public interface IFakeServiceWithOut
257+
{
258+
bool OutDecimal(out decimal num);
259+
260+
bool OutInt(out int num);
261+
}
262+
263+
public class FakeServiceWithOut : IFakeServiceWithOut
264+
{
265+
public bool OutDecimal(out decimal num)
266+
{
267+
num = 1.0M;
268+
return true;
269+
}
270+
271+
public bool OutInt(out int num)
272+
{
273+
num = 1;
274+
return true;
275+
}
276+
}
246277
}

tests/AspectCore.Tests/DynamicProxy/AsyncAspectTests.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Text;
55
using Xunit;
66
using System.Threading.Tasks;
7+
using AspectCore.DependencyInjection;
78

89
namespace AspectCore.Tests.DynamicProxy
910
{

0 commit comments

Comments
 (0)