Search code examples
c#asp.netasp.net-core.net-coresimple-injector

Integrate Simple Injector with optional ASP.NET Core Web API


I followed this guide https://simpleinjector.org/aspnetcore for getting a basic app up and running. And it works great.

My needs now are a bit different, however. The Web API in my app is basically an optional endpoint that may not be started. I want to use the Simple Injector for DI across the entire application, however.

In my Program.cs I have the following lines:

// REST API
if (Config.ReadSettingBool("StartRestEndpoint", false))
{
    LogManager.Info("Starting REST Endpoint...");
    try
    {
        _httpHost = new HttpHost(
            Config.ReadSetting("HttpHost", "localhost"),
            Config.ReadSetting("HttpPort", 8081),
            Config.ReadSetting("RestEnvironment", "Development"));
        _httpHost.Start();
        LogManager.Info("REST Endpoint started");
    }
    catch (Exception e)
    {
        LogManager.Error($"Failed to start REST endpoint: {e}");
    }
}

Now, inside the HttpHost this happens:

_webHost = WebHost.CreateDefaultBuilder()
    .UseUrls()
    .UseUrls(_url)
    .UseStartup<Startup>()
    .UseEnvironment(_environment)
    .Build();
_webHost.Start();

and inside the StartUp is the same code that I linked.

My problem is that the SimpleInjector container is kept (and setup) inside the StartUp and I have no way of getting at it. What I really want is to setup all the non-aspnet core related dependency tree prior to executing the StartUp routine and integrating with aspnet core.

That is, the "add application services" part in the below excerpt:

private void InitializeContainer(IApplicationBuilder app) {
    // Add application presentation components:
    container.RegisterMvcControllers(app);
    container.RegisterMvcViewComponents(app);

    // Add application services. For instance:
    container.Register<IUserService, UserService>(Lifestyle.Scoped);

    // Allow Simple Injector to resolve services from ASP.NET Core.
    container.AutoCrossWireAspNetComponents(app);
}

The reason for wanting this is that this app is not a pure Web Api centered around Http. It is a legacy application containing a lot of background threads doing separate work, not all of which should somehow be exposed within an web api. In some environments, the web api should not even be started. You might argue that the application should somehow be split up but given the constraints I have that is simply not an option.

In short: it solves my goal of wanting to use the same DI container, relying on the same services, persistence access and more, across the entire application, with my REST resources being able to utilize parts of the legacy application functionality.

Is this possible, and how can I accomplish that? Or am I using these tools "the wrong way"?


Solution

  • For anyone interested. I did the solution suggested by Steven. Thank you very much.

    Basically the application becomes:

                LogManager.Info("Starting REST Endpoint...");
                try
                {
                    _httpHost = new HttpHost(
                        Config.ReadSetting("HttpHost", "localhost"),
                        Config.ReadSetting("HttpPort", 8081),
                        Config.ReadSetting("RestEnvironment", "Development"));
                    _httpHost.Start();
                    LogManager.Info("REST Endpoint started");
                }
                catch (Exception e)
                {
                    LogManager.Error($"Failed to start REST endpoint: {e}");
                }
    
    
                LogManager.Info("Starting Monitors...");
                // Set up dependency tree.
                Container _container = new Container();
                BootstrapDependencyInjectionTree.Bootstrap(_container);
                _container.Verify();
    
                _monitors = new Monitors(_container.GetInstance<IMonitorDefinitionRepository>());
                _monitors.RegisterMonitors();
                _monitors.StartContinuousMonitors();
    

    with another container instance being created inside the aspnetcore StartUp type and set up as:

        private void InitializeContainer(IApplicationBuilder app)
        {
            // Add application presentation components:
            _container.RegisterMvcControllers(app);
            _container.RegisterMvcViewComponents(app);
    
            // Add application services.
            // This creates an object dependency graph that is used to populate all constructor arguments using DI.
            BootstrapDependencyInjectionTree.Bootstrap(_container);
    
            // Web api only dependencies.
            _container.RegisterSingleton<IMonitorMetaDataProvider, MonitorMetaDataProvider>();
    
            // Allow Simple Injector to resolve services from ASP.NET Core.
            _container.AutoCrossWireAspNetComponents(app);
        }
    

    This works as I would expect it.