3

I've got multiple legacy libraries which configure themselves via the ConfigurationManager. Example:

var port = ConfigurationManager.AppSettings["service.port"];

The new ASP.Net system prefers strongly typed models based on an additional "config.json" file. Example (taken from Rick Strahl's Web Log):

//from AppSettings.cs
public class AppSettings
{
    public string SiteTitle { get; set; }
}

//from config.json
{
    "AppSettings": {
        "SiteTitle": "WebApplication2",
    },
    "Data": {
        "DefaultConnection": {
            "ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=blahfoo;Trusted_Connection=True;MultipleActiveResultSets=true"
        }
    }
}

// from Startup.cs
public class Startup
{
    public IConfiguration Configuration { get; set; }

    public Startup(IHostingEnvironment env)
    {
        // Setup configuration sources.
        var configuration = new Configuration()
            .AddJsonFile("config.json")
            .AddJsonFile($"config.{env.EnvironmentName}.json", optional: true);

        configuration.AddEnvironmentVariables();
        Configuration = configuration;
    }

    public void ConfigureServices(IServiceCollection services)
    {
        // Add Application settings to the services container.
        services.Configure<AppSettings>(Configuration.GetSubKey("AppSettings"));

        …
    }
}

My question: Is there a way to embrace the new ASP.Net 5 and it's strongly typed configuration methodology while maintaining backwards compatibility with my other application libraries?

Or rather, can I utilize common libraries from our portfolio without having to rewrite them?

Will Bellman
  • 2,316
  • 1
  • 13
  • 9
  • Previous ASP.NET versions *also* had strongly typed configuration classes, otherwise you wouldn't be able to have configuration sections and specific elements. I don't think you can use the old configuration classes to load the json classes though. You *can* create common libraries but that would require rewriting the weakly-typed config code anyway – Panagiotis Kanavos Sep 17 '15 at 15:31
  • I understand. The problem is we have a lot of surface area and lots of legacy code. While I am in total agreement the legacy libraries should all be overhauled, it's not feasible at this point. What I need is a compromise that will allow me to push forward with the new technology (which mandates the Configuration class) without either maintaining multiple copies of the same libraries or rewriting entire systems. – Will Bellman Sep 17 '15 at 15:36
  • Check the [Configuration Section Designer Tool](https://csd.codeplex.com/), it allows you to design config sections and elements easily, and generate the required boilerplate code (there's a lot of it). The new model is far simpler though, so it may take some doing to convert classes from the old system to the new DTOs. Perhaps AutoMapper can help if the structures match – Panagiotis Kanavos Sep 17 '15 at 15:38
  • Sounds like you need to use the *new* classes in the *old* system, so you don't have to rewrite the old code. That's probably easier, the config system is pluggable. You could eg design a new config provider that reads from a database or Json files. There is at least one sample out there that uses the database – Panagiotis Kanavos Sep 17 '15 at 15:39
  • Found at least one sample [here](http://www.wrox.com/WileyCDA/Section/Redirecting-Configuration-with-a-Custom-Provider.id-291932.html), and a related [SO question from 2009](http://stackoverflow.com/questions/739890/read-net-configuration-from-database) – Panagiotis Kanavos Sep 17 '15 at 15:41
  • Again... still making a fundamental change to the legacy systems. ...and still rewriting significant part of the old libraries. If we have to then so be it, but then the answer to the question is "No, it can't be done, you have to rewrite a ton of stuff and potentially break the old applications or maintain multiple copies of the same library." – Will Bellman Sep 20 '15 at 19:12
  • What about reflecting through the properties of the newly created "AppSettings" object and doing something like: ConfigurationManager.AppSettings[property.Name] = property.Value? That might do it... – Will Bellman Sep 20 '15 at 19:19

1 Answers1

2

Your problem is that you relied on a concrete implementation of configuration and used the ConfigurationManager's static members from your classes instead of writing a SOLID implementation with proper dependency injection.

You could find some hacky tricks where you don't have to change your code to make use of the new configuration model, but I reckon you should do yourself a favour and use this as an opportunity to actually re-factor your code and abstract your current configurations behind one simple interface like e.g.:

public interface IMyAppConfiguration { string Setting1 { get; } string Setting2 { get; } SomeOtherMoreComplexSetting Setting3 { get; } }

Then inject this dependency in every class where you require one of the settings and provide one implementation which wraps the current ConfigurationManager class and another implementation which wraps the new configuration model.

This is a perfect example why SOLID design is important and makes code maintenance and innovation easier when done right.

dustinmoris
  • 3,195
  • 3
  • 25
  • 33