using System; using System.Linq; using System.Reflection; using Castle.DynamicProxy; using JetBrains.Annotations; using Volo.Abp; using Volo.Abp.Castle.DynamicProxy; using Volo.Abp.Http.Client; using Volo.Abp.Http.Client.DynamicProxying; namespace Microsoft.Extensions.DependencyInjection { public static class ServiceCollectionDynamicHttpClientProxyExtensions { private static readonly ProxyGenerator ProxyGeneratorInstance = new ProxyGenerator(); /// /// Registers HTTP Client Proxies for all public interfaces /// extend the interface in the /// given . /// /// Service collection /// The assembly containing the service interfaces /// /// The name of the remote service configuration to be used by the HTTP Client proxies. /// See . /// /// /// True, to register the HTTP client proxy as the default implementation for the services. /// public static IServiceCollection AddHttpClientProxies( [NotNull] this IServiceCollection services, [NotNull] Assembly assembly, [NotNull] string remoteServiceConfigurationName = RemoteServiceConfigurationDictionary.DefaultName, bool asDefaultServices = true) { Check.NotNull(services, nameof(assembly)); //TODO: Make a configuration option and add remoteServiceName inside it! //TODO: Add option to change type filter var serviceTypes = assembly.GetTypes().Where(t => t.IsInterface && t.IsPublic && typeof(IRemoteService).IsAssignableFrom(t) ); foreach (var serviceType in serviceTypes) { services.AddHttpClientProxy( serviceType, remoteServiceConfigurationName, asDefaultServices ); } return services; } /// /// Registers HTTP Client Proxy for given service type . /// /// Type of the service /// Service collection /// /// The name of the remote service configuration to be used by the HTTP Client proxy. /// See . /// /// /// True, to register the HTTP client proxy as the default implementation for the service . /// public static IServiceCollection AddHttpClientProxy( [NotNull] this IServiceCollection services, [NotNull] string remoteServiceConfigurationName = RemoteServiceConfigurationDictionary.DefaultName, bool asDefaultService = true) { return services.AddHttpClientProxy( typeof(T), remoteServiceConfigurationName, asDefaultService ); } /// /// Registers HTTP Client Proxy for given service . /// /// Service collection /// Type of the service /// /// The name of the remote service configuration to be used by the HTTP Client proxy. /// See . /// /// /// True, to register the HTTP client proxy as the default implementation for the service . /// public static IServiceCollection AddHttpClientProxy( [NotNull] this IServiceCollection services, [NotNull] Type type, [NotNull] string remoteServiceConfigurationName = RemoteServiceConfigurationDictionary.DefaultName, bool asDefaultService = true) { Check.NotNull(services, nameof(services)); Check.NotNull(type, nameof(type)); Check.NotNullOrWhiteSpace(remoteServiceConfigurationName, nameof(remoteServiceConfigurationName)); services.Configure(options => { options.HttpClientProxies[type] = new DynamicHttpClientProxyConfig(type, remoteServiceConfigurationName); }); var interceptorType = typeof(DynamicHttpProxyInterceptor<>).MakeGenericType(type); services.AddTransient(interceptorType); var interceptorAdapterType = typeof(CastleAbpInterceptorAdapter<>).MakeGenericType(interceptorType); if (asDefaultService) { services.AddTransient( type, serviceProvider => ProxyGeneratorInstance .CreateInterfaceProxyWithoutTarget( type, (IInterceptor)serviceProvider.GetRequiredService(interceptorAdapterType) ) ); } services.AddTransient( typeof(IHttpClientProxy<>).MakeGenericType(type), serviceProvider => { var service = ProxyGeneratorInstance .CreateInterfaceProxyWithoutTarget( type, (IInterceptor) serviceProvider.GetRequiredService(interceptorAdapterType) ); return Activator.CreateInstance( typeof(HttpClientProxy<>).MakeGenericType(type), service ); }); return services; } } }