/// <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);
        }
示例#2
0
        /// <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);
        }