Last active
February 7, 2023 20:08
-
-
Save norritt/add48ae376c4d79d2d253b197bff1ebd to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Originally refit is used: | |
// services | |
// .AddRefitClient<ISomething>(settingsFactory)) // we need settings factory for custom JsonSerializers | |
// .ConfigureHttpClient( | |
// (providers, client) => | |
// { | |
// var endpoints = providers.GetRequiredService<IOptions<TOptions>>(); | |
// client.BaseAddress = new Uri(urlExtractor(endpoints.Value)); | |
// }); | |
// and that stuff you should write for every interface even if they are on same server. boring | |
// Builder example: | |
// services | |
// .BuildExternalCalls() | |
// .With(jsonConverters) | |
// .Using<Endpoints>(options => options.TechCards) | |
// .To<ICheckController>() | |
// .To<IViolationController>() | |
// // .... | |
// .Build(); | |
// perhaps I should add option to omit converters, but you can't omit endpoints (there are no `Build()` method otherwise) | |
// You can choose order of With()/Using() methods as well | |
namespace Dis.Common.Refit.ExternalCall.Builder; | |
public interface IExternalCallBuilder | |
{ | |
IExternalCallNoUsingBuilder<TOptions> Using<TOptions>(Func<TOptions, string> urlExtractor) | |
where TOptions : class; | |
IExternalCallNoWithBuilder With(IReadOnlyCollection<JsonConverter> jsonConverters); | |
IExternalCallNoWithBuilder With(Func<IServiceProvider, RefitSettings> settingsFactory); | |
} | |
public interface IExternalCallNoUsingBuilder<TOptions> | |
where TOptions : class | |
{ | |
IExternalCallReadyBuilder With(IEnumerable<JsonConverter> jsonConverters); | |
IExternalCallReadyBuilder With(Func<IServiceProvider, RefitSettings> settingsFactory); | |
} | |
public interface IExternalCallNoWithBuilder | |
{ | |
IExternalCallReadyBuilder Using<TOptions>(Func<TOptions, string> urlExtractor) | |
where TOptions : class; | |
} | |
public interface IExternalCallReadyBuilder | |
{ | |
IExternalCallCompletedBuilder To<TRefitInterface>() | |
where TRefitInterface : class; | |
} | |
public interface IExternalCallCompletedBuilder : IExternalCallReadyBuilder | |
{ | |
IServiceCollection Build(); | |
} | |
internal class ExternalCallBuilder : | |
IExternalCallBuilder, | |
IExternalCallNoWithBuilder | |
{ | |
protected readonly IServiceCollection _services; | |
protected Func<IServiceProvider, RefitSettings>? _settingsFactory; | |
internal ExternalCallBuilder(IServiceCollection services, Func<IServiceProvider, RefitSettings>? settingsFactory = null) | |
{ | |
_services = services; | |
_settingsFactory = settingsFactory; | |
} | |
IExternalCallNoWithBuilder IExternalCallBuilder.With(IReadOnlyCollection<JsonConverter> jsonConverters) | |
{ | |
if (_settingsFactory != null) | |
{ | |
throw new InvalidOperationException("Settings factory already initialized"); | |
} | |
_settingsFactory = SettingsFactories.GetDefaultTokenFactory(jsonConverters); | |
return this; | |
} | |
IExternalCallNoWithBuilder IExternalCallBuilder.With(Func<IServiceProvider, RefitSettings> settingsFactory) | |
{ | |
if (_settingsFactory != null) | |
{ | |
throw new InvalidOperationException("Settings factory already initialized"); | |
} | |
_settingsFactory = settingsFactory; | |
return this; | |
} | |
IExternalCallNoUsingBuilder<TOptions> IExternalCallBuilder.Using<TOptions>(Func<TOptions, string> urlExtractor) | |
where TOptions : class | |
{ | |
return UsingInternal(urlExtractor); | |
} | |
IExternalCallReadyBuilder IExternalCallNoWithBuilder.Using<TOptions>(Func<TOptions, string> urlExtractor) | |
where TOptions : class | |
{ | |
return UsingInternal(urlExtractor); | |
} | |
protected ExternalCallBuilderWithExtractor<TOptions> UsingInternal<TOptions>(Func<TOptions, string> urlExtractor) | |
where TOptions : class | |
{ | |
if (GetType() == typeof(ExternalCallBuilderWithExtractor<TOptions>)) | |
{ | |
throw new InvalidOperationException("Url extractor already initialized"); | |
} | |
return new ExternalCallBuilderWithExtractor<TOptions>(_services, _settingsFactory, urlExtractor); | |
} | |
} | |
internal class ExternalCallBuilderWithExtractor<TOptions> : | |
ExternalCallBuilder, | |
IExternalCallNoUsingBuilder<TOptions>, | |
IExternalCallReadyBuilder, | |
IExternalCallCompletedBuilder | |
where TOptions : class | |
{ | |
private readonly Func<TOptions, string> _urlExtractor; | |
private readonly HashSet<Type> _registeredTypes = new(); | |
internal ExternalCallBuilderWithExtractor( | |
IServiceCollection services, | |
Func<IServiceProvider, RefitSettings>? settingsFactory, | |
Func<TOptions, string> urlExtractor | |
) : base(services, settingsFactory) | |
{ | |
_urlExtractor = urlExtractor; | |
} | |
IServiceCollection IExternalCallCompletedBuilder.Build() | |
{ | |
foreach (var type in _registeredTypes) | |
{ | |
_services.AddExternalCall(type, _settingsFactory, _urlExtractor); | |
} | |
return _services; | |
} | |
IExternalCallCompletedBuilder IExternalCallReadyBuilder.To<TRefitInterface>() | |
{ | |
_registeredTypes.Add(typeof(TRefitInterface)); | |
return this; | |
} | |
IExternalCallReadyBuilder IExternalCallNoUsingBuilder<TOptions>.With(IEnumerable<JsonConverter> jsonConverters) | |
{ | |
if (_settingsFactory != null) | |
{ | |
throw new InvalidOperationException("Settings factory already initialized"); | |
} | |
_settingsFactory = SettingsFactories.GetDefaultTokenFactory(jsonConverters); | |
return this; | |
} | |
IExternalCallReadyBuilder IExternalCallNoUsingBuilder<TOptions>.With(Func<IServiceProvider, RefitSettings> settingsFactory) | |
{ | |
if (_settingsFactory != null) | |
{ | |
throw new InvalidOperationException("Settings factory already initialized"); | |
} | |
_settingsFactory = settingsFactory; | |
return this; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment