Guidance on how to best register the EventGridClient with DI in a .NET 5.0 Worker Service

Ershad Nozari 421 Reputation points
2021-01-14T06:56:58.613+00:00

I'm using the EventGridClient from the Microsoft.Azure.EventGrid NuGet package to publish events to an Azure Event Grid Topic. I understand that worker services are registered with singleton lifetime. I'm looking for guidance on how to best register the EventGridClient with the DI container in a worker service? I'm using a .NET 5.0 worker hosted in a windows services.

DI registration (not sure if I've done the right thing here):

Host.CreateDefaultBuilder(args)
.UseWindowsService()
.ConfigureServices((hostContext, services) =>
{
    services.AddSingleton(new EventGridClient(new TopicCredentials("topicKey"), // proxy auth
        new HttpClientHandler {DefaultProxyCredentials = CredentialCache.DefaultCredentials}));
    services.AddHostedService<Worker>();

})
.Build()
.Run();

Worker implementation:

public class Worker : BackgroundService
{
    private readonly EventGridClient client;
    private readonly ILogger<Worker> logger;

    public Worker(EventGridClient client, ILogger<Worker> logger)
    {
        this.client = client;
        this.logger = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            var events = new List<EventGridEvent>();

            await client.PublishEventsAsync("topicHostname", events, stoppingToken);

            logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
            await Task.Delay(1000, stoppingToken);
        }
    }
}

Any guidance is highly appreciated.

Azure Event Grid
Azure Event Grid
An Azure event routing service designed for high availability, consistent performance, and dynamic scale.
321 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,391 questions
0 comments No comments
{count} votes

Accepted answer
  1. Krish G 2,326 Reputation points
    2021-01-15T16:33:09.083+00:00

    While your DI registration is technically fine and yes, it should be singleton as it involves http connection (refer Improper Instantiation antipattern for details), you can make it nicer and testable by registering the interface IEventGridClient against EventGridClient and inject IEventGridClient instead.

       //...  
       .ConfigureServices((hostContext, services) =>  
        {  
            services.AddSingleton<IEventGridClient>(new EventGridClient(new TopicCredentials("topicKey"), // proxy auth  
                new HttpClientHandler {DefaultProxyCredentials = CredentialCache.DefaultCredentials}));  
            services.AddHostedService<Worker>();  
             
        })  
    
    
    
       private readonly IEventGridClient client;  
            private readonly ILogger<Worker> logger;  
             
            public Worker(IEventGridClient client, ILogger<Worker> logger)  
            {  
                this.client = client;  
                this.logger = logger;  
            }  
    

    But note that since PublishEventsAsync is an extension method of IEventGridClient, if you write unit test for your code and inject a mock of IEventGridClient, remember to mock setup the method PublishEventsWithHttpMessages of IEventGridClient so that your test does not make a real call to event grid.

    1 person found this answer helpful.
    0 comments No comments

0 additional answers

Sort by: Most helpful