TLDR; How can I properly create a mutator that has dependencies?
I am building a solution that serialized a bag of data that is initialised by an API Middleware pipeline this data is currently registered as per LifetimeScope in, Autofac terms, I am able to resolve this dependency on the controller, but later on when I try to resolve this dependency within a mutator that should serialize the bag of data into a header, it is no longer available.
I have tried registering the Mutator with InstancePerCall and InstancePerUnitOfWork but neither gives me the object in the same state as on the controller. Does the sending pipeline create a new scope?
I have created the mutator implementing IMutateOutgoingTransportMessages and registered it through RegisterComponents(components => components.Configure<Mutator>(DependencyLifecycle.InstancePerCall)) on the EndpointConfiguration.
I’ve placed a breakpoint in the MutateOutgoing method and the constructor but I never hit the constructor, not sure why this is, but more importantly, the constructor injected dependency is no longer the initialised bag of data.
NServiceBus version 7.2.0 so I believe it is the latest.
Sending via a Message session, and indeed I only use the RegisterComponents extension on the EndpointConfiguration, also to add this is a mutator on the OutgoingTransportMessage. Is there a moment on the outgoing messaging pipeline were a new Scope is created.
With the message session there is no scope. So that means if you register your bag at the moment when the mutator is invoked whatever registration is there will be taken. So in your case because we don’t have a scope it probably makes sense to have a helper class with an AsyncLocal that you register as a singleton on the container or directly use in the mutator.
Something like
static class FloatingHeaders {
public static AsyncLocal<Dictionary<string, string>> Headers = new AsyncLocal<...>;
}
and then before the session send you set the async local value
FloatingHeaders.Headers.Value = new Dictionary<string, string>();
if you register this class as a singleton in the container then the property doesn’t have to be static but other than that it would behave equally to the static version.