Started working on a windows background service in .net that will host a restful service. As I worked on it, it seemed like Minimal APIs were a good fit (it was one of the things I was able to get a working prototype with, I couldn't get other stuff to work). However, I'm not sure if I'm misunderstanding something here. When I inspect one of my injected services, I'm noticing that it's being reconstructed each time the endpoint is hit. I didn't think that would happen if I register my services as singletons. Something tells me that due to the nature of Minimal API, there is no way around that. Am I missing something?
I'm using MessagePipe for .net.
SquareService
implements IAsyncRequestHandler<LocationByNameRequest, LocationResponse>
The registration.
builder.Services.AddMessagePipe();
builder.Services.AddSingleton<SquareService>();
The injection.
app.MapPut("/pos",
async (POS station,
IAsyncRequestHandler<LocationByNameRequest, LocationResponse> handler) => { ...});
I made sure that Visual Studio wasn't just randomly ouputing log messages, so I set up a GUID
in the constructor to verify if the instances might be different (they are).
How else would I host an api in a windows service? Been having problems integrating this, and I think it's because I'm not getting the same references as I was expecting. Any guidance would be greatly appreciated.
CodePudding user response:
That has nothing to do with Minimal APIs per se. First of all builder.Services.AddSingleton<SquareService>();
will register just SquareService
, not the interfaces it implements, if you resolve SquareService
in the handler you will get exactly the same instance every time:
app.MapPut("/pos", async (POS station, SquareService handler) => ...);
It seems that MessagePipe
has it's own custom DI/Lifetime handling. For publishers/subscribers you manipulate the registration type individually by using corresponding interfaces - see this part of the doc:
I(Async)Publisher(Subscriber)
's lifetime is belongingMessagePipeOptions.InstanceLifetime
. However if declare withISingletonPublisher<TMessage>
/ISingletonSubscriber<TKey, TMessage>
,ISingletonAsyncPublisher<TMessage>/ISingletonAsyncSubscriber<TKey, TMessage>
then used singleton lifetime. AlsoIScopedPublisher<TMessage>/IScopedSubscriber<TKey, TMessage>
,IScopedAsyncPublisher<TMessage>/IScopedAsyncSubscriber<TKey, TMessage>
uses scoped lifetime.
But for handlers the only option is to set it globally for all the handlers via MessagePipeOptions
(docs):
Configure
IRequestHandler
/IAsyncRequestHandler
's lifetime of DI container. You can chooseSingleton
orScoped
orTransient
. Default isScoped
.
services.AddMessagePipe(options => options.RequestHandlerLifetime = InstanceLifetime.Singleton);