/// <summary> /// Register a custom <see cref="IApizrManager{webApiType}"/> /// </summary> /// <param name="services">The service collection</param> /// <param name="webApiType">The web api interface type to manage</param> /// <param name="apizrManagerType">A custom <see cref="IApizrManager{webApiType}"/> implementation type</param> /// <param name="optionsBuilder">The builder defining some options</param> /// <returns></returns> public static IServiceCollection AddApizrFor( this IServiceCollection services, Type webApiType, Type apizrManagerType, Action <IApizrExtendedOptionsBuilder> optionsBuilder = null) { if (!typeof(IApizrManager <>).MakeGenericType(webApiType).IsAssignableFrom(apizrManagerType)) { throw new ArgumentException( $"Your Apizr manager class must inherit from IApizrManager generic interface or derived"); } var webApiFriendlyName = webApiType.GetFriendlyName(); var apizrOptions = CreateApizrExtendedOptions(webApiType, apizrManagerType, optionsBuilder); var builder = services.AddHttpClient(ForType(apizrOptions.WebApiType)) .ConfigurePrimaryHttpMessageHandler(serviceProvider => { var httpClientHandler = apizrOptions.HttpClientHandlerFactory.Invoke(serviceProvider); var logHandler = serviceProvider.GetRequiredService <ILogHandler>(); var handlerBuilder = new HttpHandlerBuilder(httpClientHandler, new HttpTracerLogWrapper(logHandler)); var httpTracerVerbosity = apizrOptions.HttpTracerVerbosityFactory.Invoke(serviceProvider); handlerBuilder.HttpTracerHandler.Verbosity = httpTracerVerbosity; var apizrVerbosity = apizrOptions.ApizrVerbosityFactory.Invoke(serviceProvider); if (apizrOptions.PolicyRegistryKeys != null && apizrOptions.PolicyRegistryKeys.Any()) { IReadOnlyPolicyRegistry <string> policyRegistry = null; try { policyRegistry = serviceProvider.GetRequiredService <IReadOnlyPolicyRegistry <string> >(); } catch (Exception) { if (apizrVerbosity >= ApizrLogLevel.Low) { logHandler.Write( $"Apizr - Global policies: You get some global policies but didn't register a {nameof(PolicyRegistry)} instance. Global policies will be ignored for for {webApiFriendlyName} instance"); } } if (policyRegistry != null) { foreach (var policyRegistryKey in apizrOptions.PolicyRegistryKeys) { if (policyRegistry.TryGet <IsPolicy>(policyRegistryKey, out var registeredPolicy)) { if (apizrVerbosity == ApizrLogLevel.High) { logHandler.Write($"Apizr - Global policies: Found a policy with key {policyRegistryKey} for {webApiFriendlyName} instance"); } if (registeredPolicy is IAsyncPolicy <HttpResponseMessage> registeredPolicyForHttpResponseMessage) { var policySelector = new Func <HttpRequestMessage, IAsyncPolicy <HttpResponseMessage> >( request => { var pollyContext = new Context().WithLogHandler(logHandler); HttpRequestMessageExtensions.SetPolicyExecutionContext(request, pollyContext); return(registeredPolicyForHttpResponseMessage); }); handlerBuilder.AddHandler(new PolicyHttpMessageHandler(policySelector)); if (apizrVerbosity == ApizrLogLevel.High) { logHandler.Write($"Apizr - Global policies: Policy with key {policyRegistryKey} will be applied to {webApiFriendlyName} instance"); } } else if (apizrVerbosity >= ApizrLogLevel.Low) { logHandler.Write($"Apizr - Global policies: Policy with key {policyRegistryKey} is not of {typeof(IAsyncPolicy<HttpResponseMessage>)} type and will be ignored for {webApiType.GetFriendlyName()} instance"); } } else if (apizrVerbosity >= ApizrLogLevel.Low) { logHandler.Write($"Apizr - Global policies: No policy found for key {policyRegistryKey} and will be ignored for for {webApiFriendlyName} instance"); } } } } foreach (var delegatingHandlerExtendedFactory in apizrOptions.DelegatingHandlersExtendedFactories) { handlerBuilder.AddHandler(delegatingHandlerExtendedFactory.Invoke(serviceProvider, apizrOptions)); } var primaryMessageHandler = handlerBuilder.GetPrimaryHttpMessageHandler(logHandler); return(primaryMessageHandler); }) .AddTypedClient(typeof(ILazyWebApi <>).MakeGenericType(apizrOptions.WebApiType), (client, serviceProvider) => { if (client.BaseAddress == null) { client.BaseAddress = apizrOptions.BaseAddressFactory.Invoke(serviceProvider); if (client.BaseAddress == null) { throw new ArgumentNullException(nameof(client.BaseAddress), $"You must provide a valid web api uri with the {nameof(WebApiAttribute)} or the options builder"); } } return(typeof(LazyWebApi <>).MakeGenericType(apizrOptions.WebApiType) .GetConstructor(new[] { typeof(Func <object>) }) ?.Invoke(new object[] { new Func <object>(() => RestService.For(apizrOptions.WebApiType, client, apizrOptions.RefitSettingsFactory(serviceProvider))) })); }); apizrOptions.HttpClientBuilder?.Invoke(builder); services.AddOrReplaceSingleton(typeof(IConnectivityHandler), apizrOptions.ConnectivityHandlerType); services.AddOrReplaceSingleton(typeof(ICacheHandler), apizrOptions.CacheHandlerType); services.AddOrReplaceSingleton(typeof(ILogHandler), apizrOptions.LogHandlerType); services.AddOrReplaceSingleton(typeof(IMappingHandler), apizrOptions.MappingHandlerType); services.TryAddSingleton(typeof(IApizrOptions <>).MakeGenericType(apizrOptions.WebApiType), _ => Activator.CreateInstance(typeof(ApizrOptions <>).MakeGenericType(apizrOptions.WebApiType), apizrOptions)); services.TryAddSingleton(typeof(IApizrManager <>).MakeGenericType(apizrOptions.WebApiType), typeof(ApizrManager <>).MakeGenericType(apizrOptions.WebApiType)); foreach (var postRegistrationAction in apizrOptions.PostRegistrationActions) { postRegistrationAction.Invoke(services); } return(services); }
/// <summary> /// Create a <see cref="TApizrManager"/> instance for a managed <see cref="TWebApi"/> /// </summary> /// <typeparam name="TWebApi">The web api interface to manage</typeparam> /// <typeparam name="TApizrManager">A custom <see cref="IApizrManager{TWebApi}"/> implementation</typeparam> /// <param name="apizrManagerFactory">The custom manager implementation instance factory</param> /// <param name="optionsBuilder">The builder defining some options</param> /// <returns></returns> public static TApizrManager For <TWebApi, TApizrManager>( Func <ILazyWebApi <TWebApi>, IConnectivityHandler, ICacheHandler, ILogHandler, IMappingHandler, IReadOnlyPolicyRegistry <string>, IApizrOptions <TWebApi>, TApizrManager> apizrManagerFactory, Action <IApizrOptionsBuilder> optionsBuilder = null) where TApizrManager : IApizrManager <TWebApi> { var apizrOptions = CreateApizrOptions <TWebApi>(optionsBuilder); var httpHandlerFactory = new Func <HttpMessageHandler>(() => { var httpClientHandler = apizrOptions.HttpClientHandlerFactory.Invoke(); var logHandler = apizrOptions.LogHandlerFactory.Invoke(); var handlerBuilder = new HttpHandlerBuilder(httpClientHandler, new HttpTracerLogWrapper(logHandler)); var httpTracerVerbosity = apizrOptions.HttpTracerVerbosityFactory.Invoke(); var apizrVerbosity = apizrOptions.ApizrVerbosityFactory.Invoke(); handlerBuilder.HttpTracerHandler.Verbosity = httpTracerVerbosity; if (apizrOptions.PolicyRegistryKeys != null && apizrOptions.PolicyRegistryKeys.Any()) { var policyRegistry = apizrOptions.PolicyRegistryFactory.Invoke(); foreach (var policyRegistryKey in apizrOptions.PolicyRegistryKeys) { if (policyRegistry.TryGet <IsPolicy>(policyRegistryKey, out var registeredPolicy)) { if (apizrVerbosity == ApizrLogLevel.High) { logHandler.Write($"Apizr - Global policies: Found a policy with key {policyRegistryKey}"); } if (registeredPolicy is IAsyncPolicy <HttpResponseMessage> registeredPolicyForHttpResponseMessage) { var policySelector = new Func <HttpRequestMessage, IAsyncPolicy <HttpResponseMessage> >( request => { var pollyContext = new Context().WithLogHandler(logHandler); request.SetPolicyExecutionContext(pollyContext); return(registeredPolicyForHttpResponseMessage); }); handlerBuilder.AddHandler(new PolicyHttpMessageHandler(policySelector)); if (apizrVerbosity == ApizrLogLevel.High) { logHandler.Write($"Apizr - Global policies: Policy with key {policyRegistryKey} will be applied"); } } else if (apizrVerbosity >= ApizrLogLevel.Low) { logHandler.Write($"Apizr - Global policies: Policy with key {policyRegistryKey} is not of {typeof(IAsyncPolicy<HttpResponseMessage>)} type and will be ignored"); } } else if (apizrVerbosity >= ApizrLogLevel.Low) { logHandler.Write($"Apizr - Global policies: No policy found for key {policyRegistryKey}"); } } } foreach (var delegatingHandlersFactory in apizrOptions.DelegatingHandlersFactories) { handlerBuilder.AddHandler(delegatingHandlersFactory.Invoke(logHandler, apizrOptions)); } var primaryMessageHandler = handlerBuilder.GetPrimaryHttpMessageHandler(logHandler); return(primaryMessageHandler); }); var webApiFactory = new Func <object>(() => RestService.For <TWebApi>(new HttpClient(httpHandlerFactory.Invoke(), false) { BaseAddress = apizrOptions.BaseAddressFactory.Invoke() }, apizrOptions.RefitSettingsFactory.Invoke())); var lazyWebApi = new LazyWebApi <TWebApi>(webApiFactory); var apizrManager = apizrManagerFactory(lazyWebApi, apizrOptions.ConnectivityHandlerFactory.Invoke(), apizrOptions.CacheHandlerFactory.Invoke(), apizrOptions.LogHandlerFactory.Invoke(), apizrOptions.MappingHandlerFactory.Invoke(), apizrOptions.PolicyRegistryFactory.Invoke(), new ApizrOptions <TWebApi>(apizrOptions)); return(apizrManager); }