Search code examples
c#nservicebus

Why is NServiceBus configuration broken after using TypesToScan()


I have a Console app within which you can specify parameters, based on the parameters specified various handlers will be loaded. For instance:

prgm.exe nyse 
prgm.exe nasdaq

The goal is that within my code I have INyseHandlers and INasdaqHandlers and in the first case only any handlers extending the former are loaded, similarly for the case of the latter. The goal is to have one program which can listen to various or all sources depending on how it is run. To achieve this, I have set up my interfaces as mentioned above. Then in my configuration set up:

var configuration = new BusConfiguration();
configuration.InitializeStepBusConventions(); // extension method, not the problem

// Load all the handlers specified in command line arguments
if (!Args.Contains("any") && Args.Length != 0)
{
    List<Type> handlersToLoad = new List<Type>();

    foreach (var argument in Args)
    {
        Console.WriteLine("Adding {0} subscribers to loaded handlers. . .", argument.ToUpper());

        switch (argument)
        {
            case "nyse":
                AddToHandlerList(handlersToLoad, typeof(INyseProcessor));
                break;
            case "nasdaq":
                AddToHandlerList(handlersToLoad, typeof(INasdaqProcessor));
                break;        
        }
    }

    configuration.TypesToScan(handlersToLoad);
}

configuration.UseContainer<NinjectBuilder>(c => c.ExistingKernel(Kernel));
configuration.EndpointName(ConfigurationManager.AppSettings[Defaults.Project.DefaultEndPointName]);
NServiceBus.Logging.LogManager.Use<NLogFactory>();

Bus.Create(configuration).Start();  

And where:

private void AddToHandlerList(List<Type> handlersToLoad, Type interfaceType)
{
    List<Type> classesWhichExtendInterface = Assembly.GetExecutingAssembly().GetTypes().Where(t => interfaceType.IsAssignableFrom(t)).ToList();
    classesWhichExtendInterface.Remove(interfaceType);

    handlersToLoad.AddRange(classesWhichExtendInterface);
} 

Types are loaded as expected, that List is fine. But when I run this and get to the Bus.Start line I get the following error:

The given key (NServiceBus.LocalAddress) was not present in the dictionary.

Without the type loading, default behavior works fine and all the processors within the assembly are loaded. Why am I getting this error after running the TypesToScan() line?

EDIT: Here is the extension method:

config.UseSerialization<JsonSerializer>();
config.UseTransport<RabbitMQTransport>();

config.UsePersistence<InMemoryPersistence>();
config.EnableInstallers();

return config;

Solution

  • Your exception happens here

    localAddress = Address.Parse(Settings.Get<string>("NServiceBus.LocalAddress"));
    

    Settings get the "NServiceBus.LocalAddress" kvp set by a transport. Since you are not using the "Core" transport (MSMQ), I might suspect that your transport assembly types need to be included in TypesToScan, because of this:

    ForAllTypes<Feature>(TypesToScan, t => featureActivator.Add(t.Construct<Feature>()));
    

    I had a similar issue with using SQL Server transport, when I send a list of assemblies to With(assemblies) and did not include NServiceBus assemblies there, the transport failed to initialize. As soon as I added NServiceBus.* assemblies, everything started to work.