Search code examples
dependency-injectionservicestackioc-container

ServiceStack: container.AutoWire(this) gives a NullReferenceException


If I in my AppHostBase descendant (web api project ) use container.AutoWire(this), it will result in a NullReferenceException in the ServiceStack code, if I am using a web project, thus starting it with the CreateHostBuilder(args).Build().Run(); in the main method.

The error is reproduced in this Github project: https://github.com/tedekeroth/ServiceStackAutoWireTest

The error occurs in AppHostBase.Netcore.Cs, line 158:

enter image description here

If I remove the container.AutoWire(this); in TestAppHost.cs, the error goes away, but then the dependency injection does not work, meaning the Logger in TestAppHostproperty is not assigned:

enter image description here

Why does this happen, and what can I do about it?

Setup
Visual Studio 2019
Target framework: .NET 5.0 (Console Application)
Project SDK: Microsoft.NET.Sdk.Web
ServiceStack 5.11.0


Solution

  • The IOC AutoWire API attempts to autowire all public property dependencies of an object which is definitely something you should never attempt to do with the AppHost which encapsulates the configuration and behavior of your ServiceStack App where indiscriminatingly overriding every public property is going to leave it in a corrupted state.

    Registering your AppHost in the IOC shouldn't be necessary as it's available everywhere via the HostContext.AppHost singleton. It's also a bad idea trying to reference any type defined in your Host Project, (the AppHost being the canonical example) since it creates a circular reference to your Host project in your App logic dependencies which shouldn't have any references back to its Host project, your Host project is supposed to reference all your projects .dll's, configure your App's and all its dependencies, not the other way around.

    Should you need access to any Plugins it's recommended to use the GetPlugin<T>() API in your Service for optional plugins or AssertPlugin<T>() for required plugins. If you need to resolve any deps manually you can use TryResolve<T>() API in your Service class. For any of your App's custom config I'd recommend registering them in a custom AppConfig class for your Services to access like any other dependencies.

    Otherwise if you really need access to the AppHost you can use the HostContext.AppHost singleton. If you absolutely need to have the AppHost in the IOC, just register it as a normal singleton, i.e. don't try to autowire it:

    container.Register<IAppHost>(c => this);
    

    However as mentioned earlier I'd strongly advise against it, have everything your App needs in a custom class (e.g. AppConfig) that is accessed like a normal dependency.