user12398280
user12398280

Reputation: 137

Where and how should I initialize service which is used for sending requests like HttpClient?

I am using Google Vision API and its C# library.

I want to understand where should I initialize ImageAnnotatorClient and how should I register GoogleVisionApiService. ImageAnnotatorClient is used for sending images to the Google Vision API, like this _imageAnnotatorClient.DetectSafeSearchAsync(image)

First way - register service as Singleton and initialize ImageAnnotatorClient in the constructor

public class GoogleVisionApiService : IGoogleVisionApiService
{
    private readonly IGoogleCredentialFactory _googleCredentialFactory;
    private readonly ImageAnnotatorClient _imageAnnotatorClient;

    public GoogleVisionApiService(IGoogleCredentialFactory googleCredentialFactory) 
    {
        _googleCredentialFactory = googleCredentialFactory;
        _imageAnnotatorClient = InitializeClient();
    }

    private ImageAnnotatorClient InitializeClient()
    {
        var googleCredential = _googleCredentialFactory.GetGoogleCredentialAsync().Result;
        var credential = googleCredential.UnderlyingCredential as ServiceAccountCredential;
        
        var imageAnnotatorClientBuilder = new ImageAnnotatorClientBuilder
        {
            Credential = credential
        };

        var imageAnnotatorClient = imageAnnotatorClientBuilder.Build();
        
        return imageAnnotatorClient;
    }
    
    public async Task<SafeSearchAnnotation> GetSafeSearchAnnotationAsync(string imageBase64)
    {        
        var image = Image.FromBytes(Convert.FromBase64String(requestImage));

        var labels = await _imageAnnotatorClient.DetectSafeSearchAsync(image);

        return labels;
    }
}   

Second way is to register service as Transient and initialize client every time service is called

public class GoogleVisionApiService : IGoogleVisionApiService
{
    private readonly IGoogleCredentialFactory _googleCredentialFactory;

    public GoogleVisionApiService(IGoogleCredentialFactory googleCredentialFactory) 
    {
        _googleCredentialFactory = googleCredentialFactory;
    }

    public async Task<SafeSearchAnnotation> GetSafeSearchAnnotationAsync(string imageBase64)
    {      
        var googleCredential = await _googleCredentialFactory.GetGoogleCredentialAsync();
        var credential = googleCredential.UnderlyingCredential as ServiceAccountCredential;
        
        var imageAnnotatorClientBuilder = new ImageAnnotatorClientBuilder
        {
            Credential = credential
        };

        var imageAnnotatorClient = await imageAnnotatorClientBuilder.BuildAsync();  

        var image = Image.FromBytes(Convert.FromBase64String(requestImage));

        var labels = await _imageAnnotatorClient.DetectSafeSearchAsync(image);

        return labels;
    }
} 

Upvotes: 1

Views: 590

Answers (1)

Jon Skeet
Jon Skeet

Reputation: 1502406

In general, it's best to create a single RPC client if you can.

In your specific case, I'd suggest using the (relatively new) DI-friendly extension methods in the Google client libraries. Then your GoogleVisionApiService can just accept an ImageAnnotatorClient.

// Wherever you're configuring services
services
    // Make sure everything uses the right credential
    .AddSingleton<GoogleCredential>(provider => /* code to fetch credential */)
    // Note: this is for .NET 6 and .NET Core 3.1. Without this line, the client builder
    // will use the "right" adapter for the environment, but won't be able to hook gRPC
    // logging up with the DI's logging configuration
    .AddGrpcNetClientAdapter()
    .AddImageAnnotatorClient();

See the client lifecycle docs for more information.

Upvotes: 1

Related Questions