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 chooseSingletonorScopedorTransient. Default isScoped.
services.AddMessagePipe(options => options.RequestHandlerLifetime = InstanceLifetime.Singleton);
