Browse Source

Use Castle.Core.AsyncInterceptor

pull/2464/head
Halil İbrahim Kalkan 7 years ago
parent
commit
f6084749f9
  1. 2
      framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs
  2. 1
      framework/src/Volo.Abp.Castle.Core/Volo.Abp.Castle.Core.csproj
  3. 2
      framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/AbpCastleCoreModule.cs
  4. 15
      framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/AbpAsyncDeterminationInterceptor.cs
  5. 73
      framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpInterceptorAdapter.cs
  6. 55
      framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapter.cs
  7. 48
      framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapterBase.cs
  8. 27
      framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapterWithReturnValue.cs
  9. 36
      framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAsyncAbpInterceptorAdapter.cs
  10. 6
      framework/src/Volo.Abp.Http.Client/Microsoft/Extensions/DependencyInjection/ServiceCollectionDynamicHttpClientProxyExtensions.cs
  11. 28
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs

2
framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs

@ -89,7 +89,7 @@ namespace Autofac.Builder
foreach (var interceptor in interceptors)
{
registrationBuilder.InterceptedBy(
typeof(CastleAbpInterceptorAdapter<>).MakeGenericType(interceptor)
typeof(AbpAsyncDeterminationInterceptor<>).MakeGenericType(interceptor)
);
}

1
framework/src/Volo.Abp.Castle.Core/Volo.Abp.Castle.Core.csproj

@ -15,6 +15,7 @@
<ItemGroup>
<PackageReference Include="Castle.Core" Version="4.4.0" />
<PackageReference Include="Castle.Core.AsyncInterceptor" Version="2.0.21-alpha" />
</ItemGroup>
<ItemGroup>

2
framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/AbpCastleCoreModule.cs

@ -8,7 +8,7 @@ namespace Volo.Abp.Castle
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddTransient(typeof(CastleAbpInterceptorAdapter<>));
context.Services.AddTransient(typeof(AbpAsyncDeterminationInterceptor<>));
}
}
}

15
framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/AbpAsyncDeterminationInterceptor.cs

@ -0,0 +1,15 @@
using Castle.DynamicProxy;
using Volo.Abp.DynamicProxy;
namespace Volo.Abp.Castle.DynamicProxy
{
public class AbpAsyncDeterminationInterceptor<TInterceptor> : AsyncDeterminationInterceptor
where TInterceptor : IAbpInterceptor
{
public AbpAsyncDeterminationInterceptor(TInterceptor abpInterceptor)
: base(new CastleAsyncAbpInterceptorAdapter<TInterceptor>(abpInterceptor))
{
}
}
}

73
framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpInterceptorAdapter.cs

@ -1,73 +0,0 @@
using System.Reflection;
using System.Threading.Tasks;
using Castle.DynamicProxy;
using Volo.Abp.DynamicProxy;
using Volo.Abp.Threading;
namespace Volo.Abp.Castle.DynamicProxy
{
public class CastleAbpInterceptorAdapter<TInterceptor> : IInterceptor
where TInterceptor : IAbpInterceptor
{
private static readonly MethodInfo MethodExecuteWithReturnValueAsync =
typeof(CastleAbpInterceptorAdapter<TInterceptor>)
.GetMethod(
nameof(ExecuteWithReturnValueAsync),
BindingFlags.NonPublic | BindingFlags.Instance
);
private readonly TInterceptor _abpInterceptor;
public CastleAbpInterceptorAdapter(TInterceptor abpInterceptor)
{
_abpInterceptor = abpInterceptor;
}
public void Intercept(IInvocation invocation)
{
var proceedInfo = invocation.CaptureProceedInfo();
var method = invocation.MethodInvocationTarget ?? invocation.Method;
if (!method.IsAsync())
{
proceedInfo.Invoke();
return;
}
InterceptAsyncMethod(invocation, proceedInfo);
}
private void InterceptAsyncMethod(IInvocation invocation, IInvocationProceedInfo proceedInfo)
{
if (invocation.Method.ReturnType == typeof(Task))
{
invocation.ReturnValue = ExecuteWithoutReturnValueAsync(invocation, proceedInfo);
}
else
{
invocation.ReturnValue = MethodExecuteWithReturnValueAsync
.MakeGenericMethod(invocation.Method.ReturnType.GenericTypeArguments[0])
.Invoke(this, new object[] {invocation, proceedInfo});
}
}
private async Task ExecuteWithoutReturnValueAsync(IInvocation invocation, IInvocationProceedInfo proceedInfo)
{
await _abpInterceptor.InterceptAsync(
new CastleAbpMethodInvocationAdapter(invocation, proceedInfo)
);
}
private async Task<T> ExecuteWithReturnValueAsync<T>(IInvocation invocation, IInvocationProceedInfo proceedInfo)
{
await Task.Yield();
await _abpInterceptor.InterceptAsync(
new CastleAbpMethodInvocationAdapter(invocation, proceedInfo)
);
return await (Task<T>)invocation.ReturnValue;
}
}
}

55
framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapter.cs

@ -1,65 +1,26 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading.Tasks;
using Castle.DynamicProxy;
using Volo.Abp.DynamicProxy;
using Volo.Abp.Threading;
namespace Volo.Abp.Castle.DynamicProxy
{
public class CastleAbpMethodInvocationAdapter : IAbpMethodInvocation
public class CastleAbpMethodInvocationAdapter : CastleAbpMethodInvocationAdapterBase, IAbpMethodInvocation
{
public object[] Arguments => Invocation.Arguments;
public IReadOnlyDictionary<string, object> ArgumentsDictionary => _lazyArgumentsDictionary.Value;
private readonly Lazy<IReadOnlyDictionary<string, object>> _lazyArgumentsDictionary;
public Type[] GenericArguments => Invocation.GenericArguments;
public object TargetObject => Invocation.InvocationTarget ?? Invocation.MethodInvocationTarget;
public MethodInfo Method => Invocation.MethodInvocationTarget ?? Invocation.Method;
public object ReturnValue
{
get => _actualReturnValue ?? Invocation.ReturnValue;
set => Invocation.ReturnValue = value;
}
private object _actualReturnValue;
protected IInvocation Invocation { get; }
protected IInvocationProceedInfo ProceedInfo { get; }
protected Func<IInvocation, IInvocationProceedInfo, Task> Proceed { get; }
public CastleAbpMethodInvocationAdapter(IInvocation invocation, IInvocationProceedInfo proceedInfo)
public CastleAbpMethodInvocationAdapter(IInvocation invocation, IInvocationProceedInfo proceedInfo,
Func<IInvocation, IInvocationProceedInfo, Task> proceed)
: base(invocation)
{
Invocation = invocation;
ProceedInfo = proceedInfo;
_lazyArgumentsDictionary = new Lazy<IReadOnlyDictionary<string, object>>(GetArgumentsDictionary);
}
public Task ProceedAsync()
{
ProceedInfo.Invoke();
_actualReturnValue = Invocation.ReturnValue;
return (Task) _actualReturnValue;
Proceed = proceed;
}
private IReadOnlyDictionary<string, object> GetArgumentsDictionary()
public override async Task ProceedAsync()
{
var dict = new Dictionary<string, object>();
var methodParameters = Method.GetParameters();
for (int i = 0; i < methodParameters.Length; i++)
{
dict[methodParameters[i].Name] = Invocation.Arguments[i];
}
return dict;
await Proceed(Invocation, ProceedInfo);
}
}
}

48
framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapterBase.cs

@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading.Tasks;
using Castle.DynamicProxy;
using Volo.Abp.DynamicProxy;
namespace Volo.Abp.Castle.DynamicProxy
{
public abstract class CastleAbpMethodInvocationAdapterBase : IAbpMethodInvocation
{
public object[] Arguments => Invocation.Arguments;
public IReadOnlyDictionary<string, object> ArgumentsDictionary => _lazyArgumentsDictionary.Value;
private readonly Lazy<IReadOnlyDictionary<string, object>> _lazyArgumentsDictionary;
public Type[] GenericArguments => Invocation.GenericArguments;
public object TargetObject => Invocation.InvocationTarget ?? Invocation.MethodInvocationTarget;
public MethodInfo Method => Invocation.MethodInvocationTarget ?? Invocation.Method;
public object ReturnValue { get; set; }
protected IInvocation Invocation { get; }
protected CastleAbpMethodInvocationAdapterBase(IInvocation invocation)
{
Invocation = invocation;
_lazyArgumentsDictionary = new Lazy<IReadOnlyDictionary<string, object>>(GetArgumentsDictionary);
}
public abstract Task ProceedAsync();
private IReadOnlyDictionary<string, object> GetArgumentsDictionary()
{
var dict = new Dictionary<string, object>();
var methodParameters = Method.GetParameters();
for (int i = 0; i < methodParameters.Length; i++)
{
dict[methodParameters[i].Name] = Invocation.Arguments[i];
}
return dict;
}
}
}

27
framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapterWithReturnValue.cs

@ -0,0 +1,27 @@
using System;
using System.Threading.Tasks;
using Castle.DynamicProxy;
using Volo.Abp.DynamicProxy;
namespace Volo.Abp.Castle.DynamicProxy
{
public class CastleAbpMethodInvocationAdapterWithReturnValue<TResult> : CastleAbpMethodInvocationAdapterBase, IAbpMethodInvocation
{
protected IInvocationProceedInfo ProceedInfo { get; }
protected Func<IInvocation, IInvocationProceedInfo, Task<TResult>> Proceed { get; }
public CastleAbpMethodInvocationAdapterWithReturnValue(IInvocation invocation,
IInvocationProceedInfo proceedInfo,
Func<IInvocation, IInvocationProceedInfo, Task<TResult>> proceed)
: base(invocation)
{
ProceedInfo = proceedInfo;
Proceed = proceed;
}
public override async Task ProceedAsync()
{
ReturnValue = await Proceed(Invocation, ProceedInfo);
}
}
}

36
framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAsyncAbpInterceptorAdapter.cs

@ -0,0 +1,36 @@
using System;
using System.Threading.Tasks;
using Castle.DynamicProxy;
using Volo.Abp.DynamicProxy;
namespace Volo.Abp.Castle.DynamicProxy
{
public class CastleAsyncAbpInterceptorAdapter<TInterceptor> : AsyncInterceptorBase
where TInterceptor : IAbpInterceptor
{
private readonly TInterceptor _abpInterceptor;
public CastleAsyncAbpInterceptorAdapter(TInterceptor abpInterceptor)
{
_abpInterceptor = abpInterceptor;
}
protected override async Task InterceptAsync(IInvocation invocation, IInvocationProceedInfo proceedInfo, Func<IInvocation, IInvocationProceedInfo, Task> proceed)
{
await _abpInterceptor.InterceptAsync(
new CastleAbpMethodInvocationAdapter(invocation, proceedInfo, proceed)
);
}
protected override async Task<TResult> InterceptAsync<TResult>(IInvocation invocation, IInvocationProceedInfo proceedInfo, Func<IInvocation, IInvocationProceedInfo, Task<TResult>> proceed)
{
var adapter = new CastleAbpMethodInvocationAdapterWithReturnValue<TResult>(invocation, proceedInfo, proceed);
await _abpInterceptor.InterceptAsync(
adapter
);
return (TResult)adapter.ReturnValue;
}
}
}

6
framework/src/Volo.Abp.Http.Client/Microsoft/Extensions/DependencyInjection/ServiceCollectionDynamicHttpClientProxyExtensions.cs

@ -53,7 +53,7 @@ namespace Microsoft.Extensions.DependencyInjection
foreach (var serviceType in serviceTypes)
{
services.AddHttpClientProxy(
serviceType,
serviceType,
remoteServiceConfigurationName,
asDefaultServices
);
@ -153,7 +153,7 @@ namespace Microsoft.Extensions.DependencyInjection
var interceptorType = typeof(DynamicHttpProxyInterceptor<>).MakeGenericType(type);
services.AddTransient(interceptorType);
var interceptorAdapterType = typeof(CastleAbpInterceptorAdapter<>).MakeGenericType(interceptorType);
var interceptorAdapterType = typeof(AbpAsyncDeterminationInterceptor<>).MakeGenericType(interceptorType);
if (asDefaultService)
{
@ -174,7 +174,7 @@ namespace Microsoft.Extensions.DependencyInjection
var service = ProxyGeneratorInstance
.CreateInterfaceProxyWithoutTarget(
type,
(IInterceptor) serviceProvider.GetRequiredService(interceptorAdapterType)
(IInterceptor)serviceProvider.GetRequiredService(interceptorAdapterType)
);
return Activator.CreateInstance(

28
framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs

@ -74,18 +74,33 @@ namespace Volo.Abp.Http.Client.DynamicProxying
Logger = NullLogger<DynamicHttpProxyInterceptor<TService>>.Instance;
}
public override Task InterceptAsync(IAbpMethodInvocation invocation)
public override async Task InterceptAsync(IAbpMethodInvocation invocation)
{
if (invocation.Method.ReturnType.GenericTypeArguments.IsNullOrEmpty())
{
return MakeRequestAsync(invocation);
await MakeRequestAsync(invocation);
}
else
{
var result = (Task)GenericInterceptAsyncMethod
.MakeGenericMethod(invocation.Method.ReturnType.GenericTypeArguments[0])
.Invoke(this, new object[] { invocation });
invocation.ReturnValue = GenericInterceptAsyncMethod
.MakeGenericMethod(invocation.Method.ReturnType.GenericTypeArguments[0])
.Invoke(this, new object[] { invocation });
invocation.ReturnValue = await GetResultAsync(
result,
invocation.Method.ReturnType.GetGenericArguments()[0]
);
}
return Task.CompletedTask;
}
private async Task<object> GetResultAsync(Task task, Type resultType)
{
await task;
return typeof(Task<>)
.MakeGenericType(resultType)
.GetProperty(nameof(Task<object>.Result), BindingFlags.Instance | BindingFlags.Public)
.GetValue(task);
}
private async Task<T> MakeRequestAndGetResultAsync<T>(IAbpMethodInvocation invocation)
@ -138,7 +153,6 @@ namespace Volo.Abp.Http.Client.DynamicProxying
return await response.Content.ReadAsStringAsync();
}
private ApiVersionInfo GetApiVersionInfo(ActionApiDescriptionModel action)
{
var apiVersion = FindBestApiVersion(action);

Loading…
Cancel
Save