Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions src/AspectCore.Core/Utils/ProxyGeneratorUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -569,12 +569,14 @@ void EmitMethodBody()
{
if (parameters[i].IsByRef)
{
Type byrefToType = parameters[i].GetElementType();

ilGen.EmitLoadArg(i + 1);
ilGen.Emit(OpCodes.Ldloc, argsLocal);
ilGen.EmitInt(i);
ilGen.Emit(OpCodes.Ldelem_Ref);
ilGen.EmitConvertFromObject(parameters[i].GetElementType());
ilGen.EmitStRef(parameters[i]);
ilGen.EmitStRef(byrefToType);
}
}
if (!method.IsVoid())
Expand Down Expand Up @@ -622,12 +624,14 @@ void EmitProxyMethodBody()
{
if (parameterTypes[i].IsByRef)
{
Type byrefToType = parameterTypes[i].GetElementType();

ilGen.EmitLoadArg(i + 1);
ilGen.Emit(OpCodes.Ldloc, parameters);
ilGen.EmitInt(i);
ilGen.Emit(OpCodes.Ldelem_Ref);
ilGen.EmitConvertFromObject(parameterTypes[i].GetElementType());
ilGen.EmitStRef(parameterTypes[i]);
ilGen.EmitConvertFromObject(byrefToType);
ilGen.EmitStRef(byrefToType);
}
}
}
Expand Down Expand Up @@ -928,7 +932,7 @@ private static void CopyDefaultValueConstant(ParameterInfo from, ParameterBuilde
// If this bug is present, it is caused by a `null` default value:
defaultValue = null;
}
catch (FormatException) when (from.ParameterType.GetTypeInfo().IsEnum)
catch (FormatException) when (from.ParameterType.IsEnum)
{
// This catch clause guards against a CLR bug that makes it impossible to query
// the default value of a (closed generic) enum parameter. For the CoreCLR, see
Expand Down Expand Up @@ -973,7 +977,7 @@ private static void CopyDefaultValueConstant(ParameterInfo from, ParameterBuilde
// would "produce" a default value of `Missing.Value` in this situation).
return;
}
else if (parameterType.GetTypeInfo().IsValueType)
else if (parameterType.IsValueType)
{
// This guards against a CLR bug that prohibits replicating `null` default
// values for non-nullable value types (which, despite the apparent type
Expand All @@ -989,7 +993,7 @@ private static void CopyDefaultValueConstant(ParameterInfo from, ParameterBuilde
else if (isNullableType)
{
parameterNonNullableType = from.ParameterType.GetGenericArguments()[0];
if (parameterNonNullableType.GetTypeInfo().IsEnum || parameterNonNullableType.IsInstanceOfType(defaultValue))
if (parameterNonNullableType.IsEnum || parameterNonNullableType.IsInstanceOfType(defaultValue))
{
// This guards against two bugs:
//
Expand Down
166 changes: 81 additions & 85 deletions src/AspectCore.Extensions.Reflection/Emit/ILGeneratorExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -210,25 +210,17 @@ public static void EmitCastToType(this ILGenerator ilGenerator, TypeInfo typeFro
{
throw new ArgumentNullException(nameof(ilGenerator));
}
if (!typeFrom.IsValueType && typeTo.IsValueType)
if (typeFrom.IsValueType)
{
ilGenerator.Emit(OpCodes.Unbox_Any, typeTo.AsType());
}
else if (typeFrom.IsValueType && !typeTo.IsValueType)
{
ilGenerator.Emit(OpCodes.Box, typeFrom.AsType());
if (typeTo.AsType() != typeof(object))
ilGenerator.Emit(OpCodes.Box, typeFrom);
if (typeTo != typeof(object))
{
ilGenerator.Emit(OpCodes.Castclass, typeTo.AsType());
ilGenerator.Emit(OpCodes.Castclass, typeTo);
}
}
else if (!typeFrom.IsValueType && !typeTo.IsValueType)
{
ilGenerator.Emit(OpCodes.Castclass, typeTo.AsType());
}
else
{
throw new InvalidCastException($"Caanot cast {typeFrom} to {typeTo}.");
ilGenerator.Emit(typeTo.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass, typeTo);
}
}

Expand Down Expand Up @@ -693,49 +685,48 @@ public static void EmitLdRef(this ILGenerator ilGenerator, Type type)
{
throw new ArgumentNullException(nameof(type));
}
if (type == typeof(short))
{
ilGenerator.Emit(OpCodes.Ldind_I1);
}
else if (type == typeof(Int16))
{
ilGenerator.Emit(OpCodes.Ldind_I2);
}
else if (type == typeof(Int32))
{
ilGenerator.Emit(OpCodes.Ldind_I4);
}
else if (type == typeof(Int64))
{
ilGenerator.Emit(OpCodes.Ldind_I8);
}
else if (type == typeof(float))
{
ilGenerator.Emit(OpCodes.Ldind_R4);
}
else if (type == typeof(double))
{
ilGenerator.Emit(OpCodes.Ldind_R8);
}
else if (type == typeof(ushort))
{
ilGenerator.Emit(OpCodes.Ldind_U1);
}
else if (type == typeof(UInt16))
{
ilGenerator.Emit(OpCodes.Ldind_U2);
}
else if (type == typeof(UInt32))
{
ilGenerator.Emit(OpCodes.Ldind_U4);
}
else if (type.GetTypeInfo().IsValueType)
{
ilGenerator.Emit(OpCodes.Ldobj);
}
else
switch (Type.GetTypeCode(type))
{
ilGenerator.Emit(OpCodes.Ldind_Ref);
case TypeCode.SByte:
ilGenerator.Emit(OpCodes.Ldind_I1);
break;
case TypeCode.Boolean:
case TypeCode.Byte:
ilGenerator.Emit(OpCodes.Ldind_U1);
break;
case TypeCode.Int16:
ilGenerator.Emit(OpCodes.Ldind_I2);
break;
case TypeCode.Char:
case TypeCode.UInt16:
ilGenerator.Emit(OpCodes.Ldind_U2);
break;
case TypeCode.Int32:
ilGenerator.Emit(OpCodes.Ldind_I4);
break;
case TypeCode.UInt32:
ilGenerator.Emit(OpCodes.Ldind_U4);
break;
case TypeCode.Int64:
case TypeCode.UInt64:
ilGenerator.Emit(OpCodes.Ldind_I8);
break;
case TypeCode.Single:
ilGenerator.Emit(OpCodes.Ldind_R4);
break;
case TypeCode.Double:
ilGenerator.Emit(OpCodes.Ldind_R8);
break;
default:
if (type.IsValueType)
{
ilGenerator.Emit(OpCodes.Ldobj, type);
}
else
{
ilGenerator.Emit(OpCodes.Ldind_Ref);
}
break;
}
}

Expand All @@ -749,37 +740,42 @@ public static void EmitStRef(this ILGenerator ilGenerator, Type type)
{
throw new ArgumentNullException(nameof(type));
}
if (type == typeof(short))
{
ilGenerator.Emit(OpCodes.Stind_I1);
}
else if (type == typeof(Int16))
{
ilGenerator.Emit(OpCodes.Stind_I2);
}
else if (type == typeof(Int32))
{
ilGenerator.Emit(OpCodes.Stind_I4);
}
else if (type == typeof(Int64))
{
ilGenerator.Emit(OpCodes.Stind_I8);
}
else if (type == typeof(float))
{
ilGenerator.Emit(OpCodes.Stind_R4);
}
else if (type == typeof(double))
{
ilGenerator.Emit(OpCodes.Stind_R8);
}
else if (type.GetTypeInfo().IsValueType)
{
ilGenerator.Emit(OpCodes.Stobj);
}
else
switch (Type.GetTypeCode(type))
{
ilGenerator.Emit(OpCodes.Stind_Ref);
case TypeCode.Boolean:
case TypeCode.Byte:
case TypeCode.SByte:
ilGenerator.Emit(OpCodes.Stind_I1);
break;
case TypeCode.Char:
case TypeCode.Int16:
case TypeCode.UInt16:
ilGenerator.Emit(OpCodes.Stind_I2);
break;
case TypeCode.Int32:
case TypeCode.UInt32:
ilGenerator.Emit(OpCodes.Stind_I4);
break;
case TypeCode.Int64:
case TypeCode.UInt64:
ilGenerator.Emit(OpCodes.Stind_I8);
break;
case TypeCode.Single:
ilGenerator.Emit(OpCodes.Stind_R4);
break;
case TypeCode.Double:
ilGenerator.Emit(OpCodes.Stind_R8);
break;
default:
if (type.IsValueType)
{
ilGenerator.Emit(OpCodes.Stobj, type);
}
else
{
ilGenerator.Emit(OpCodes.Stind_Ref);
}
break;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@
</PackageReference>
<PackageReference Include="System.Runtime.Serialization.Primitives" Version="4.3.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="System.Reflection" Version="4.3.0" />
<PackageReference Include="System.Linq" Version="4.3.0" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System.Globalization;
using System.Threading.Tasks;
using AspectCore.DynamicProxy;

namespace AspectCore.Extensions.Test.Fakes
{
public class FakeServiceWithOutInterceptor : AbstractInterceptorAttribute
{
public override async Task Invoke(AspectContext context, AspectDelegate next)
{
await next(context);
}
}

[FakeServiceWithOutInterceptor]
public interface IFakeServiceWithOut
{
bool OutDecimal(out decimal num);

bool OutInt(out int num);
}

public class FakeServiceWithOut : IFakeServiceWithOut
{
public bool OutDecimal(out decimal num)
{
num = 1.0M;
return true;
}

public bool OutInt(out int num)
{
num = 1;
return true;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Reflection;
using AspectCore.Configuration;
using AspectCore.DependencyInjection;
using AspectCore.DynamicProxy;
using AspectCore.Extensions.Autofac;
using AspectCore.Extensions.Test.Fakes;
Expand Down Expand Up @@ -67,5 +68,31 @@ public void AsProxyWithParamter_Test()
var proxyController = container.Resolve<IController>();
Assert.Equal(proxyService.Get(100), proxyController.Execute());
}

[Fact]
public void Intercept_OutWithDecimalParamter_Test()
{
var builder = CreateBuilder();
builder.RegisterType<FakeServiceWithOut>().As<IFakeServiceWithOut>();
var container = builder.Build();

var proxyServiceWithOut = container.Resolve<IFakeServiceWithOut>();
decimal num;
Assert.True(proxyServiceWithOut.OutDecimal(out num));
Assert.Equal(1.0M, num);
}

[Fact]
public void Intercept_OutWithIntParamter_Test()
{
var builder = CreateBuilder();
builder.RegisterType<FakeServiceWithOut>().As<IFakeServiceWithOut>();
var container = builder.Build();

var proxyServiceWithOut = container.Resolve<IFakeServiceWithOut>();
int num;
Assert.True(proxyServiceWithOut.OutInt(out num));
Assert.Equal(1, num);
}
}
}
31 changes: 31 additions & 0 deletions tests/AspectCore.Tests/Classes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -243,4 +243,35 @@ string IFakeExplicitImplementation.GetVal_NonAspect()
return "lemon";
}
}

public class FakeServiceWithOutInterceptor : AbstractInterceptorAttribute
{
public override async Task Invoke(AspectContext context, AspectDelegate next)
{
await next(context);
}
}

[FakeServiceWithOutInterceptor]
public interface IFakeServiceWithOut
{
bool OutDecimal(out decimal num);

bool OutInt(out int num);
}

public class FakeServiceWithOut : IFakeServiceWithOut
{
public bool OutDecimal(out decimal num)
{
num = 1.0M;
return true;
}

public bool OutInt(out int num)
{
num = 1;
return true;
}
}
}
1 change: 1 addition & 0 deletions tests/AspectCore.Tests/DynamicProxy/AsyncAspectTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Text;
using Xunit;
using System.Threading.Tasks;
using AspectCore.DependencyInjection;

namespace AspectCore.Tests.DynamicProxy
{
Expand Down
Loading