2

As part of my application I have a .Net Core API project. Unlike most cases where this project would run as its own process, I intend to have the API run in a thread, among others, in a single process. The reason for this is that the API acts as a web interface, operating on the same level as a local console interface. Both interfaces share a singleton object and perform operations on it (asynchronously). At least that is the plan. However, I have run into a problem.

I have this Startup.cs for the API:

public class Startup
{
    public Startup(IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
            .AddEnvironmentVariables();
        this.Configuration = builder.Build();
    }

    public IConfigurationRoot Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {.
        services.AddMvc();
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        loggerFactory.AddConsole(this.Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();

        app.UseMvc();
    }
}

..which is the default with a few minor changes, and this method used to start the API:

public static void Run()
{
    var host = new WebHostBuilder()
        .UseKestrel()
        .UseContentRoot(Directory.GetCurrentDirectory())
        .UseIISIntegration()
        .UseStartup<Startup>()
        .Build();

    host.Run();
}

What I cannot figure out is how to pass my instantiated object to the Startup so that I can then register it as a singleton and have it work with the controllers.

Is there a way to do this? If not, then what other approach could I take?

stelioslogothetis
  • 9,371
  • 3
  • 28
  • 53

1 Answers1

1

What is the problem to create your object and register it as singleton in StartupServices?

services.AddSingleton<ISingleton>(new MySingleton());
services.AddSingleton(new MySingleton());

Or you can provide a Func to make the creation lazy and provide dependencies:

services.AddSingleton(provider =>
{
    var fooDependency = provider.GetService<FooDependency>();

    return new MySingleton(fooDependency);
});

Or you can delegate the object creation to factory class (lazy too):

services.AddSingleton(provider => provider.GetService<MyFactory>().CreateMySingleton());

Documentation: Service Lifetimes and Registration Options.

Ilya Chumakov
  • 23,161
  • 9
  • 86
  • 114
  • The problem is that the object is already created when I instantiate the `Startup`. As far as I'm aware, registering it like youre describing creates a new instance. What im trying to do is pass the already existing instance to the `Startup` and go on from there. – stelioslogothetis Apr 29 '17 at 09:57
  • @Sty, you absolutely aren't need to create a new instance. Instead, pass the existing instance to `Startup`. In other words. create a singleton without DI and then pass it to DI. There are a lot of ways to create a singleton in C#: http://csharpindepth.com/Articles/General/Singleton.aspx Moreover, you can extend `Startup.ConfigureServices` method: http://stackoverflow.com/a/43653118/5112433 – Ilya Chumakov Apr 29 '17 at 10:14
  • Thats what the question was. How to pass my object to the startup. Sorry if I didnt phrase it well. – stelioslogothetis Apr 29 '17 at 11:08
  • @Sty check the last option from the article (`Lazy` type). Then just call `.AddSingleton(Singleton.Instance)` in `ConfigureServices`. – Ilya Chumakov Apr 29 '17 at 12:56