ASP.NET Core: Dependency Injection and custom classes


Dependency injection is one of the new features of ASP.NET Core which allows you to register your own services or have core services injected into classes like controllers.  In order to have an object injected it must be registered and then be passed in via the constructor of a class which would look something like this:

Controller Code (C#)

private readonly IHostingEnvironment HostingEnvironment {get; set;}

public HomeController(IHostingEnvironment env)
{ 
    HostingEnvironment = env;
}

In the above, the hosting environment would be injected into the home controller and then saved into a property where it can be used through the life cycle of the said controller (and then passed down the line to other classes in the most common scenario). This separates concerns and allows for greater testability.

The question I will answer today is how you can use dependency injection within a custom class without constructor injection. I will provide an example below but also caveat this would probably be considered an anti-pattern.

In the below example we will create a simple SiteUtilites class that provides access to the hosting environment in order to get the base content path of a site (similiar to the Server.MapPath of old). The trick is adding a static property to the class and then setting it when the site starts up at the time the object is injected into the Configure method.

SiteUtilities.cs (C#)

public static class SiteUtilities
{

    public static IHostingEnvironment HostingEnvironment { get; set; }

    public static SqliteConnection GetOpenGameDbConnection()
    {
        // A sample sqlite database to open a connection to
        string connectionString = HostingEnvironment.ContentRootPath + @"\Data\test.db";

        SqliteConnection conn = new SqliteConnection($"Data Source={connectionString}");
        conn.Open();
        return conn;
    }

}

Configure Method of Startup.cs (C#)

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        loggerFactory.AddConsole();
        
        if (env.IsDevelopment())
        {                
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
        }

        app.UseStaticFiles();
        app.UseMvcWithDefaultRoute();

        // Have to be careful with static properties, they persist throughout the life time
        // of the application.  
        SiteUtilities.HostingEnvironment = env;
    }

In the Configure method the static property for the hosting model is set to the value that was injected into Configure. There are a few behaviors here that you should note (and can test in the debugger). The Configure method is called when the site starts, anything set statically is set once when that executes. The static property though is global in a sense. For example, if you put a Stopwatch property in via this method and started it, it would continue to run throughout the lifetime of the site (now imagine how quickly that could get you into trouble if used improperly).

Leave a comment

Please note that we won't show your email to others, or use it for sending unwanted emails. We will only use it to render your Gravatar image and to validate you as a real person.