Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / WinForms

Lifecycle Profile Settings

4.50/5 (2 votes)
6 Jan 2009CPOL3 min read 29.3K   217  
A simple mechanism for partitioning settings for development, acceptance, and production.

settings_1.gif

Introduction

This article demonstrates a simple solution to using different Property.Settings for applications in development, acceptance, and production environments. This can be extended for using the same code base for different clients where the connection strings and other settings may be different.

Background

Visual Studio (and the .NET Framework) offers a convenient solution to adding and using application scope variables via the Settings on the Project Property pages. When different environments are configured for lifecycle stages (development, acceptance testing, and production deployment), the settings may need to be constantly changed at these stages. Connection strings and shared resource locations are the obvious settings, among others. This solution promotes the use of separate XML data files for each of the profiles (development, acceptance, and production), and the process of promoting the code base prior to deployment is as simple as changing one setting. In fact, I have found it easier to manage if the only settings in the Settings Designer are the location of the current profile file and any connection strings (as settings) used by the designers or code-behind. All of the other settings can sit in the XML data file, and be accessed via the included library API.

Using the code

The included solution has a library, a quick and dirty settings designer (I find the raw XML is just as easy), and two test harnesses. C# and VB.NET test harnesses have been supplied because the code-behind of the settings file in C# does not enumerate the built-in events.

The steps for using the test harnesses:

  1. From the Settings Designer (Project > Properties > Settings), assign the setting runtimeSettingsFile to either Profile1.xml or Profile2.xml.
  2. Run the project.
  3. Note the data entries and the border color of the form.
  4. Close the form.
  5. From the Settings Designer, assign the setting runtimeSettingsFile to either Profile1.xml or Profile2.xml (not the last setting).
  6. Run the project.
  7. Notice the data entries and border color have changed to reflect the values in the XML file. Although very simple, the two runtimeSettings represent different values used in development, acceptance, or production.

The steps for using the library from your project:

  1. Add a reference from your project to the library emx.Properties
  2. Create XML data files with all of the settings needed for each environment
  3. Set the properties of these XML files (BuildAction=Content, Copy to Output Directory=Copy, if newer)
  4. xml_properties.jpg

  5. Add the following code to the Settings.vb or Settings.cs file (from Project > Properties > Settings > View Code)
  6. view_code.jpg

    C#
    // C#
    
    using emx.Properties;
    using System;
    
    namespace emx.Properties.TestHarnessCS.Properties {
        
        
        // This class allows you to handle specific events on the settings class:
        //  The SettingChanging event is raised before a setting's value is changed.
        //  The PropertyChanged event is raised after a setting's value is changed.
        //  The SettingsLoaded event is raised after the setting values are loaded.
        //  The SettingsSaving event is raised before the setting values are saved.
        internal sealed partial class Settings {
            
            public Settings() {
                SettingsLoaded += SettingsLoadedHandler;
            }
            
            private void SettingsLoadedHandler(object sender, 
                         System.Configuration.SettingsLoadedEventArgs e)
            {
                // build the settings filename with the value assigned
                // in Settings : System.Configuration.ApplicationSettingsBase 
                string s_xmlFile = System.IO.Path.Combine(_
                  System.Windows.Forms.Application.StartupPath, _
                  this["runtimeSettingsFile"].ToString());
                if (!System.IO.File.Exists(s_xmlFile)){
                    // under normal circumstances this
                    // should only happen in development
                    System.Windows.Forms.MessageBox.Show(
                       "File does not exist:\n" + s_xmlFile);
                }else{
                    try{
                        // set the global property
                        // to a new instance of the RuntimeSettings
                        emx.Properties.Globals.currentRuntimeSettings = 
                                              new RuntimeSettings(s_xmlFile);
                        // set any paired settings back
                        // into the Application Properties Settings
                        emx.Properties.Globals.currentRuntimeSettings.assignSettings(this);
                    }catch (RuntimeSettingsException ex){
                        // under normal circumstances this
                        // should only happen in development
                        System.Windows.Forms.MessageBox.Show(ex.Message + 
                           "\nkey = " + ex.key + 
                           "\ndataType = " + ex.dataType);
                    }
                }
            }
    
        }
    }

    VB.NET:

    VB.NET
    // 
    ' VB.NET
    
    Namespace My
        
        'This class allows you to handle specific events on the settings class:
        ' The SettingChanging event is raised before a setting's value is changed.
        ' The PropertyChanged event is raised after a setting's value is changed.
        ' The SettingsLoaded event is raised after the setting values are loaded.
        ' The SettingsSaving event is raised before the setting values are saved.
        Partial Friend NotInheritable Class MySettings
    
    
            Private Sub MySettings_SettingsLoaded(ByVal sender As Object, _
                    ByVal e As System.Configuration.SettingsLoadedEventArgs) _
                    Handles Me.SettingsLoaded
                ' build the settings filename with the value assigned
                ' in Settings : System.Configuration.ApplicationSettingsBase 
                Dim s_xmlFile As String = System.IO.Path.Combine(_
                  System.Windows.Forms.Application.StartupPath, _
                  Me("runtimeSettingsFile").ToString())
                If Not System.IO.File.Exists(s_xmlFile) Then
                    ' under normal circumstances this should only happen in development
                    System.Windows.Forms.MessageBox.Show("File does" & _ 
                                   " not exist:\n" & s_xmlFile)
                Else
                    Try
                        ' set the global property to a new instance of the RuntimeSettings
                        emx.Properties.Globals.currentRuntimeSettings = _
                                       New RuntimeSettings(s_xmlFile)
                        '[ set any paired settings back
                        '  into the Application Properties Settings
                        emx.Properties.Globals.currentRuntimeSettings.assignSettings(Me)
                    Catch ex As RuntimeSettingsException
                        ' under normal circumstances this should only happen in development
                        System.Windows.Forms.MessageBox.Show(ex.Message + _
                           "\nkey = " & ex.key & _
                           "\ndataType = " & ex.dataType)
                    End Try
                End If
            End Sub
    
    
        End Class
    End Namespace
  7. Add the setting runtimeSettingsFile with the name of the current XML file in the Settings Designer
  8. Run your project

Points of interest

Mechanisms for updating the values of settings (connection strings included) via the Settings code-behind are discussed frequently, but I have not seen a generic component/library that manages this process. The SettingsLoaded event is used because it is fired before any values accessed via the Settings object are used. I am sure this process can be optimized possibly by using the SettingsBase class instead of the strongly typed Settings class.

The following class diagram annotates some of the features:

class_diagram.jpg

History

  • 2009-01-08 - Minor layout edits.
  • 2009-01-07 - Article submitted.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)