C
C#4mo ago
frobnicate

How to avoid the Service Locator anti pattern when needing to instantiate multiple of a DI instance?

I have a Typed Client (Service Agent) as per https://learn.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-8.0#typed-clients, and it is consumed in a class as a ctor DI, but I need to instantiate a new instance per request.† So instead I currently use a Service Locator, which is an anti pattern, and thus I'd like to avoid this. I'm not sure how a factory would solve it, since then I'd just move the DI instantiating problem to the factory. Code example of what I have:
public class MyService
{
public MyService(HttpClient httpClient)
{
// ....
}

public async Task<Whatever> MyEndpoint()
{
return await _httpClient //...
}
}

public class MyConsumer<T> where T : class
{
public MyConsumer(IServiceProvider serviceProvider)
{
// ...
}

public async Task<Foobar> PerformMultipleRequests()
{
//some loop
var myService = _serviceProvider.GetRequiredService<T>();
myService.MyEndpoint()
// ...
}
}
public class MyService
{
public MyService(HttpClient httpClient)
{
// ....
}

public async Task<Whatever> MyEndpoint()
{
return await _httpClient //...
}
}

public class MyConsumer<T> where T : class
{
public MyConsumer(IServiceProvider serviceProvider)
{
// ...
}

public async Task<Foobar> PerformMultipleRequests()
{
//some loop
var myService = _serviceProvider.GetRequiredService<T>();
myService.MyEndpoint()
// ...
}
}
† The reason I need to spawn a client / service per request, is that the endpoint I'm writing against doesn't accept multiple simultaneous requests from the same client. Right now I'm just building around it but hopefully it'll get fixed
22 Replies
Tvde1
Tvde14mo ago
Why does the limitation of the external API make it so you need to create a scope? I can imagine you'd want your MyService to be a Singleton, to manage that there will only be one concurrent request
frobnicate
frobnicate4mo ago
Because I need multiple requests to run in parrallel, and the external API does not allow multiple concurrent requests from the same client
Tvde1
Tvde14mo ago
What do you mean "from the same client"? is it a HTTP call and identified by a header or user agent?
frobnicate
frobnicate4mo ago
In practice, when I use the same instance of a HttpClient, to do multiple requests on the API, it will fail. If I make a HttpClient per request, it works. I'm not sure why It's a different company that makes the external API and they haven't documented it :catshrug:
Tvde1
Tvde14mo ago
just curious, how do you notice it fails? Do you get a certain response?
frobnicate
frobnicate4mo ago
500
Tvde1
Tvde14mo ago
oopsie I think I'd make MyService a transient/scoped, and it'll get a IHttpClientFactory that way, MyConsumer can rely on MyService to do the right logic you want this weird behavior to be in your MyService such that if it ever changes, you change the single part responsible for it
frobnicate
frobnicate4mo ago
So MyService has a ctor DI IHttpClientFactory?
Tvde1
Tvde14mo ago
yes
Tvde1
Tvde14mo ago
Use the IHttpClientFactory - .NET
Learn how to use the HttpClient and IHttpClientFactory implementations with dependency injection in your .NET workloads.
frobnicate
frobnicate4mo ago
I had hoped I could do it with typed clients :c Oh well
Tvde1
Tvde14mo ago
I don't really get the point of typed clients, but that might just be me
frobnicate
frobnicate4mo ago
Not needing to use strings and being able to put more behaviour in the service But thanks regardless! How do I mark it as solved?
Tvde1
Tvde14mo ago
you can use /close but feel free to open again or ask another question 😁
Unknown User
Unknown User4mo ago
Message Not Public
Sign In & Join Server To View
frobnicate
frobnicate4mo ago
If I make a queue do they run in parallel?
Unknown User
Unknown User4mo ago
Message Not Public
Sign In & Join Server To View
frobnicate
frobnicate4mo ago
But if I queue with a single client I have the same issue of not having multiple concurrent requests
Unknown User
Unknown User4mo ago
Message Not Public
Sign In & Join Server To View
frobnicate
frobnicate4mo ago
The requests are slow, that's why I want them to be in parallel
Unknown User
Unknown User4mo ago
Message Not Public
Sign In & Join Server To View
frobnicate
frobnicate4mo ago
Ok