dependency-injectionnservicebusnservicebus3

NServiceBus Dependency Injection


I've been having a bit of trouble with this.

Andreas Öhlund answered a question on it here, but I've been unable to get it to work using the advice he gave.

Here's my setup:

public abstract class CommandHandler<T> : IHandleMessages<T>, IDomainReadRepository where T : Command
{
    public IDomainRepository DomainRepository { get; set; }

    protected abstract void OnProcess(T command);

    public TAggregate GetById<TAggregate>(Guid id) where TAggregate : IEventProvider, new()
    {
        return DomainRepository.GetById<TAggregate>(id);
    }

    public void Handle(T message)
    {
        OnProcess(message);
        // Domain repository will save.
    }
}

The idea is specific command handlers override the OnProcess method and do their thing, then the DomainRepository will save everything.

Here is how I've registered the components:

public class EndpointConfig : IConfigureThisEndpoint, AsA_Server, IWantCustomInitialization
{
    public void Init()
    {
        Configure.With().DefiningCommandsAs(c => c.Namespace != null && c.Namespace.EndsWith("Commands"));
        Configure.Instance.DefaultBuilder().Configurer.ConfigureComponent<DomainRepository>(DependencyLifecycle.InstancePerCall);
        Configure.Instance.DefaultBuilder().Configurer.ConfigureComponent<EventStore.Sql.EventStore>(DependencyLifecycle.InstancePerCall);
        Configure.Instance.DefaultBuilder().Configurer.ConfigureComponent<MongoDbObjectSecurityDescriptorRepository>(DependencyLifecycle.InstancePerCall);
        Configure.Instance.DefaultBuilder().Configurer.ConfigureComponent<LocalTenantConfig>(DependencyLifecycle.InstancePerCall);
    }
}

Those are all the objects down the chain that are used by the DomainRepository; however, when I receive a command, the DomainRepository is null. If I comment out the lines to register the objects that DomainRepository needs, I'll actually get an error saying it failed to create it (Autofac DependencyResolutionException).

It should be noted that all the other objects use constructor injection (they're taken from a previously existing project). I tried changing them to use public property injection, but it didn't make any difference.

It would be much appreciated if somebody could point out what I'm doing wrong here!


Solution

  • Move the code in your init method into a different class which implements INeedInitialization. In there, use Configure.Instance instead of Configure.With() and also instead of Configure.Instance.DefaultBuilder().