How to use different .settings files for different environments in .NET?
Asked Answered
D

6

11

.NET allows you to use .settings files to manage application settings. I would like to store Production, Development and Test settings separately in a way that I can do something like this:

EnvironmentSettings environmentSettings;

// get the current environment (Production, Development or Test)
ApplicationEnvironment Environment = (ApplicationEnvironment)
    Enum.Parse(typeof(ApplicationEnvironment), Settings.Default.ApplicationEnvironment);

switch (Environment)
{
    case ApplicationEnvironment.Production:
        environmentSettings = Settings.Production;
        break;
    ...
}

string reportOutputLocation = environmentSettings.ReportOutputLocation;

Basically, I want two separate Settings classes: the general Settings class that stores the selected environment and non-environment specific properties, and 3 static instances of a second class called EnvironmentSettings. The instance used should depend on the environment specified in the general Settings class.

Is there any way to do this short of manually setting the values for all these settings in a static constructor or something? If I have to do that, I'd rather just have one big Settings class with properties like "DevOutputLocation", "LiveOutputLocation", etc.

I can have multiple .settings files in my project but that just creates separate classes that don't derive from each other. So I could make DevelopmentSettings.settings, ProductionSettings.settings and TestSettings.settings files and give them the same properties, but then I would need a bunch of switch statements everywhere to determine which class to use because they don't derive from a common class.

Digitate answered 11/2, 2010 at 19:38 Comment(1)
you could do this by using a different user for each environment, but somehow I think that cause more problems than it solves.Overnice
B
2

I am using this approach for .config files, I am sure that it will help you too. Just look on Scott Hanselman's blog post and this question. Ideology is simple like hell, but works pretty good. All you will need is:

  1. create several files for different configurations
  2. name them by convention, e.g. my.dev.settings, my.live.settings
  3. create post build event (see links)
  4. enjoy =)

Instantiation code for you class with settings will always look in default settings (which will be replaced after each build with the needed one), so this approach require minimal effort.

Blockus answered 12/2, 2010 at 9:13 Comment(3)
Is this really the only way? I suppose so if it's endorsed by Scott H. It just seems like a really messy hack. You would think you could specify what .settings or .config file to use for each build configuration.Digitate
I was just going back through my previously-asked questions and noticed I never marked this as answered so there you go. Thanks again.Digitate
Another possibility is to use an XML transform tool like SlowCheetahChess
A
3

One thought is that switching between a series of static values sounds like a rather fraught way of doing things. I would suggest looking up the Singleton pattern. This pattern gives you a single class instance that is shared between all references to the class, but when it's first loaded you can do your normal initialisation bits to check your environment and set the values accordingly.

Equally, rather than using switches to act on different classes, wouldn't you be looking at designing one Interface, and having each class implement that interface?

Authentic answered 11/2, 2010 at 23:4 Comment(0)
B
2

I am using this approach for .config files, I am sure that it will help you too. Just look on Scott Hanselman's blog post and this question. Ideology is simple like hell, but works pretty good. All you will need is:

  1. create several files for different configurations
  2. name them by convention, e.g. my.dev.settings, my.live.settings
  3. create post build event (see links)
  4. enjoy =)

Instantiation code for you class with settings will always look in default settings (which will be replaced after each build with the needed one), so this approach require minimal effort.

Blockus answered 12/2, 2010 at 9:13 Comment(3)
Is this really the only way? I suppose so if it's endorsed by Scott H. It just seems like a really messy hack. You would think you could specify what .settings or .config file to use for each build configuration.Digitate
I was just going back through my previously-asked questions and noticed I never marked this as answered so there you go. Thanks again.Digitate
Another possibility is to use an XML transform tool like SlowCheetahChess
I
1

There is a bit of overhead involved in making a check to determine what environment you are running in. If you are talking a web environment then this could mean a significant performance hit. I would recommend creating three separate config files and setting up a continuous integration and deployment system that handles the naming and roll out of the proper settings file based on environment. In your case you would have three files, Production.config, Development.config, and Test.config. The integration server would then create a copy of this file for web.config or app.config based on the environment.

As far as any additional maintenance involved with maintaining three separate files whenever a configuration change is made, we keep the files auto-formatted and use something like WinMerge to easily see differences and keep them in proper sync. These type of files typically do not require many changes and when they do they are usually minor additions.

Iverson answered 12/2, 2010 at 20:17 Comment(0)
S
1

I currently do something similar to the solution mentioned by pdavis. But to simplifying multiple config files I use a T4 templates to create the environment specific config files. That way there is one web.tt file that handles the generation of the default web.config file. Each environment has its own template file (qa.tt, production.tt, etc) that inherits from web.tt and contains any environment specific overrides. Any changes to web config - new app settings, configuration settings, etc. are automatically propagated to all region specific config files by regenerating the templates, and you don't have to worry about keeping files in sync using a diff tool.

Subminiaturize answered 13/2, 2010 at 4:33 Comment(0)
H
0

Just an idea but it may work...

  • You'll need N+2 settings files (N different builds; 2 masters) with containing the same keys.

  • Clear out the "Custom Tool" property for all of them but one of the masters (so only one the master generates).

  • Modify the pre-build script for each release to copy the appropriate settings file contents into the build-master file.

  • Modify the post-build script to copy the secondary master file contents back in to the original master file.

Note: If you can work with your source control provider in the pre- and post-build scripts, you don't need a secondary master -- you can just check out in the pre-build and undo check out in the post-build. However, this may cause issues in a continuous integration environment since a locked file would require the build to fail.

I've also never done this; though there are times I wished there was a more up-front way of doing something like this in VS.

Hexane answered 11/2, 2010 at 20:52 Comment(0)
D
0

Just some extra info on .NET environment based config files without using your above implementation specifically:

The Enterprise Library has this feature since V3.0: Summary

Visual Studio 2010 will have this feature also. Its called Config Transformation

Decidua answered 12/2, 2010 at 19:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.