mirror of https://github.com/abpframework/abp.git
10 changed files with 181 additions and 41 deletions
@ -0,0 +1,41 @@ |
|||
using System; |
|||
using Castle.DynamicProxy; |
|||
using Volo.Abp.Castle.DynamicProxy; |
|||
using Volo.Abp.Http; |
|||
using Volo.Abp.Http.DynamicProxying; |
|||
|
|||
namespace Microsoft.Extensions.DependencyInjection |
|||
{ |
|||
public static class ServiceCollectionDynamicHttpClientProxyExtensions |
|||
{ |
|||
private static readonly ProxyGenerator ProxyGeneratorInstance = new ProxyGenerator(); |
|||
|
|||
//TODO: AddHttpClientProxies for adding all services from single assembly!
|
|||
|
|||
public static IServiceCollection AddHttpClientProxy<T>(this IServiceCollection services, string baseUrl) |
|||
{ |
|||
return services.AddHttpClientProxy(typeof(T), baseUrl); |
|||
} |
|||
|
|||
public static IServiceCollection AddHttpClientProxy(this IServiceCollection services, Type type, string baseUrl) |
|||
{ |
|||
services.Configure<AbpHttpOptions>(options => |
|||
{ |
|||
options.HttpClientProxies[type] = new DynamicHttpClientProxyConfig(type, baseUrl); |
|||
}); |
|||
|
|||
var interceptorType = typeof(DynamicHttpProxyInterceptor<>).MakeGenericType(type); |
|||
services.AddTransient(interceptorType); |
|||
|
|||
var interceptorAdapterType = typeof(CastleAbpInterceptorAdapter<>).MakeGenericType(interceptorType); |
|||
return services.AddTransient( |
|||
type, |
|||
serviceProvider => ProxyGeneratorInstance |
|||
.CreateInterfaceProxyWithoutTarget( |
|||
type, |
|||
(IInterceptor) serviceProvider.GetRequiredService(interceptorAdapterType) |
|||
) |
|||
); |
|||
} |
|||
} |
|||
} |
|||
@ -1,32 +0,0 @@ |
|||
using System; |
|||
using Castle.DynamicProxy; |
|||
using Volo.Abp.Castle.DynamicProxy; |
|||
using Volo.Abp.Http; |
|||
using Volo.Abp.Http.DynamicProxying; |
|||
|
|||
namespace Microsoft.Extensions.DependencyInjection |
|||
{ |
|||
public static class ServiceCollectionHttpProxyExtensions |
|||
{ |
|||
private static readonly ProxyGenerator ProxyGeneratorInstance = new ProxyGenerator(); |
|||
|
|||
public static IServiceCollection AddHttpClientProxy<T>(this IServiceCollection services, string baseUrl) |
|||
{ |
|||
return services.AddHttpClientProxy(typeof(T), baseUrl); |
|||
} |
|||
|
|||
public static IServiceCollection AddHttpClientProxy(this IServiceCollection services, Type type, string baseUrl) |
|||
{ |
|||
services.AddTransient(type, serviceProvider => |
|||
{ |
|||
return ProxyGeneratorInstance |
|||
.CreateInterfaceProxyWithoutTarget( |
|||
type, |
|||
serviceProvider.GetRequiredService<CastleAbpInterceptorAdapter<DynamicHttpProxyInterceptor>>() |
|||
); |
|||
}); |
|||
|
|||
return services; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using Volo.Abp.Http.DynamicProxying; |
|||
|
|||
namespace Volo.Abp.Http |
|||
{ |
|||
public class AbpHttpOptions |
|||
{ |
|||
public Dictionary<Type, DynamicHttpClientProxyConfig> HttpClientProxies { get; set; } |
|||
|
|||
public AbpHttpOptions() |
|||
{ |
|||
HttpClientProxies = new Dictionary<Type, DynamicHttpClientProxyConfig>(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,66 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using Newtonsoft.Json; |
|||
using Newtonsoft.Json.Serialization; |
|||
using Nito.AsyncEx; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Http.Modeling; |
|||
|
|||
namespace Volo.Abp.Http.DynamicProxying |
|||
{ |
|||
public class ApplicationApiDescriptionModelCache : IApplicationApiDescriptionModelCache, ISingletonDependency |
|||
{ |
|||
private readonly IDynamicProxyHttpClientFactory _httpClientFactory; |
|||
|
|||
private readonly Dictionary<string, ApplicationApiDescriptionModel> _cache; |
|||
private readonly AsyncLock _asyncLock; |
|||
|
|||
public ApplicationApiDescriptionModelCache(IDynamicProxyHttpClientFactory httpClientFactory) |
|||
{ |
|||
_httpClientFactory = httpClientFactory; |
|||
|
|||
_cache = new Dictionary<string, ApplicationApiDescriptionModel>(); |
|||
_asyncLock = new AsyncLock(); |
|||
} |
|||
|
|||
public async Task<ApplicationApiDescriptionModel> GetAsync(string baseUrl, CancellationToken cancellationToken = default(CancellationToken)) |
|||
{ |
|||
using (await _asyncLock.LockAsync(cancellationToken)) |
|||
{ |
|||
var model = _cache.GetOrDefault(baseUrl); |
|||
if (model == null) |
|||
{ |
|||
_cache[baseUrl] = model = await GetModelFromRemoteServer(baseUrl); |
|||
} |
|||
|
|||
return model; |
|||
} |
|||
} |
|||
|
|||
private async Task<ApplicationApiDescriptionModel> GetModelFromRemoteServer(string baseUrl) |
|||
{ |
|||
using (var client = _httpClientFactory.Create()) |
|||
{ |
|||
var response = await client.GetAsync(baseUrl + "api/abp/api-description"); |
|||
if (!response.IsSuccessStatusCode) |
|||
{ |
|||
throw new AbpException("Remote service returns error!"); |
|||
} |
|||
|
|||
var content = await response.Content.ReadAsStringAsync(); |
|||
|
|||
var result = JsonConvert.DeserializeObject( |
|||
content, |
|||
typeof(ApplicationApiDescriptionModel), |
|||
new JsonSerializerSettings |
|||
{ |
|||
ContractResolver = new CamelCasePropertyNamesContractResolver() |
|||
}); |
|||
|
|||
return (ApplicationApiDescriptionModel)result; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
using System; |
|||
|
|||
namespace Volo.Abp.Http.DynamicProxying |
|||
{ |
|||
public class DynamicHttpClientProxyConfig |
|||
{ |
|||
public Type Type { get; } |
|||
|
|||
public string BaseUrl { get; } |
|||
|
|||
public DynamicHttpClientProxyConfig(Type type, string baseUrl) |
|||
{ |
|||
Type = type; |
|||
BaseUrl = baseUrl; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
using System; |
|||
using System.Collections.Concurrent; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Http.Modeling; |
|||
|
|||
namespace Volo.Abp.Http.DynamicProxying |
|||
{ |
|||
public interface IApplicationApiDescriptionModelCache |
|||
{ |
|||
Task<ApplicationApiDescriptionModel> GetAsync(string baseUrl, CancellationToken cancellationToken = default(CancellationToken)); |
|||
} |
|||
} |
|||
Loading…
Reference in new issue