I have service class which loads data from external service. This service needs API key which loads from db and unique for every user.
public class GoogleCloudService
{
private readonly ILogger<GoogleCloudService> logger;
public GoogleCloudService(string key)
{
Key = key;
logger = Startup.ServiceProvider.GetService<ILogger<GoogleCloudService>>();
}
public string Key { get; set; }
public async Task<string> ImageTextRecognizeAsync(byte[] imageBytes, string type = "TEXT_DETECTION", string languageHints = "en-t-i0-handwrit")
{
string url = "https://vision.googleapis.com/v1/images:annotate"
+ "?key=" + Key;
using (var client = new HttpClient())
{
try
{
var values = new
{
requests = new[]
{
new {
image = new { content = Convert.ToBase64String(imageBytes) },
features = new[] { new { type = type } },
imageContext = new { languageHints = new[] { languageHints } }
}
}
};
var response = await client.PostAsJsonAsync(url, values);
try
{
response.EnsureSuccessStatusCode();
var jsonSettings = new JsonSerializerOptions();
jsonSettings.Converters.Add(new DynamicJsonConverter());
dynamic responseJson = await response.Content.ReadFromJsonAsync<dynamic>(jsonSettings);
if (responseJson is not null && responseJson.responses is not null && responseJson.responses[0] is not null && responseJson.responses[0].fullTextAnnotation is not null)
{
return responseJson.responses[0].fullTextAnnotation.text;
}
else
{
return null;
}
throw new HttpRequestException();
}
catch (Exception ex)
{
ex.Data.Add("Request", await response.RequestMessage.ToRawAsync());
ex.Data.Add("Response", await response.ToRawAsync());
throw;
}
}
catch (Exception ex)
{
logger.LogError(ex, "Возникла ошибка при отправке запроса в Google Cloud.");
}
}
return null;
}
}
and usage:
var gService = new GoogleCloudService(entityDB.GoogleApiKey);
string text = await gService.ImageTextRecognizeAsync(imageBytes);
Everything works fine, but I think using global ServiceProvider from static Startup.ServiceProvider is not a good idea. How can I eliminate service locator pattern and configure service key dynamically by user in code? What are best practices?
public GoogleCloudService(string key, ILogger<GoogleCloudService> logger)- the constructor must accept one more parameter \$\endgroup\$