top of page

How to Use Settings for a Class Library

Application settings allow you to configure an application after it's been deployed. For example, your application may use a database connection string or the file path of its help document. Rather than hard-coding these values in your code, you can place them in a configuration file.


In Visual Studio, you can easily add settings to your application. Right-click on your main project and select Properties. In the Properties page, select Settings. If your application doesn't have settings already, you'll see the message, "This project does not contain a default settings file. Click here to create one." When you click on it, you'll be able to add your own settings.


This way of using settings, however, only works for executable applications. It doesn't work for class libraries (or binary plug-in scripts for Eclipse). In this blog post, I'll show you a slightly different way of managing settings that works for class libraries.


First, let's look at the problem again. You can actually follow the steps above to add application settings to a class library. As in an application, Visual Studio will add an "app.config" (or "App.config") file to your project. This file contains the settings you added in the Properties page, and they are placed inside the <applicationSettings> section.


In your class library, you can use the automatically generated Settings class to access your added settings:


using MyScript.Properties;
using VMS.TPS.Common.Model.API;

namespace VMS.TPS
{
    public class Script
    {
        public void Execute(ScriptContext context)
        {
            var mySetting = Settings.Default.MySetting;
        }
    }
}

For this example, I created a setting named "MySetting".


When you use your setting in a script like this, it seems to work because your setting returns the value you entered when you first created the setting. When you change the value in the configuration file, however, you'll notice that your script continues to use the original value.


What!?


The problem is that your script never used the configuration file in the first place—it couldn't find it. Because it couldn't find the settings, it used the default values that were hard-coded in the Settings class Visual Studio generated for you.


The reason the script couldn't file the settings is that the configuration file it used was the application's, not the class library. For an Eclipse plug-in script, the application is Eclipse itself, which likely doesn't have the settings you added to your class library. This is just the way the Settings class works—it access the application's configuration file, not the library's.


We need to ditch the Settings class and manually read the settings from the class library's configuration file. We also need to use a slightly different way of specifying settings in the configuration file.


If you created a new class library, and therefore don't have a configuration file, you can add it by right-clicking on your project, select Add and then Add New Item. Then, choose "Application Configuration File".


First, let's add the new settings in the configuration file:


<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="MySetting1" value="MyValue1" />
    <add key="MySetting2" value="MyValue2" />
  </appSettings>
</configuration>

Notice that the settings must be inside a tag named <appSettings>, and each setting is added by using the <add> tag as shown above. The setting value must be a string. Be aware that if you have sensitive data (e.g., a server name) you may not want to commit this into version control. You may want to change the setting's value to a dummy value before you commit.


Now, add the following class to your project:


internal class AssemblySettings
{
    public static string MySetting1 => GetAppSetting("MySetting1");
    public static string MySetting2 => GetAppSetting("MySetting2");

    private static string GetAppSetting(string key)
    {
        try
        {
            var asmPath = Assembly.GetExecutingAssembly().Location;
            var config = ConfigurationManager.OpenExeConfiguration(asmPath);
            var setting = config.AppSettings.Settings[key];
            return setting.Value;
        }
        catch (Exception e)
        {
            throw new InvalidOperationException("Error reading configuration setting", e);
        }
    }
}

MySetting1 and MySetting2 are static properties that call GetAppSetting using the name of the setting in the configuration file. GetAppSetting does the work of loading the configuration file of the current class library (or assembly), and then obtaining the setting's value. I adapted this code from an answer on StackOverflow.


You can now use this class as follows:


using MyScript.Properties;
using VMS.TPS.Common.Model.API;

namespace VMS.TPS
{
    public class Script
    {
        public void Execute(ScriptContext context)
        {
            var mySetting1 = AssemblySettings.MySetting1;
            var mySetting2 = AssemblySettings.MySetting2;
        }
    }
}

Now, when you change a setting's value in the configuration file, the correct one will be used.


Be aware that the location of the configuration file is, by default, in the same directory as the class library itself. This means that if different users are running the same script assembly, then the same configuration settings will be used. Changing a setting changes it for every user.


In addition to <appSettings>, you can also have <connectionStrings> to maintain your database connection strings. You can manually read those from the configuration file as well, calling ConnectionStrings on the config object instead of AppSettings. For more information on why you may want to keep settings and connection strings separately, see this answer on StackOverflow.

Related Posts

See All

ESAPI Essentials 1.1 and 2.0

A few months ago, I introduced ESAPI Essentials—a toolkit for working with ESAPI (available via NuGet). I've recently added one major feature: asynchronous access to ESAPI for binary plugin scripts. Y

Announcement: ESAPI Subreddit

A few months ago, Matt Schmidt started the ESAPI subreddit. It's another useful resource for finding and discussing ESAPI-related topics. According to the description, This community is to post and di

Dump All Patient Data from ESAPI

If, for whatever reason, you need to dump out all of the data for a patient from ESAPI, there's a quick and dirty way to do it. Well, there are probably several ways to do it, but here's one I've foun

Comments


bottom of page