Question

I have a dll that I want to read from a manually specified app.config file (the dll is an .net extension to a native com dll that is a Microsoft Management Console snap in, so there is no mmc.exe.config). I have been able to open the config file, read the relevant group and section to get the setting that I want. Like this:

ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
            fileMap.ExeConfigFilename = Assembly.GetExecutingAssembly().Location + ".config"; 
            Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
            ShowSectionGroupCollectionInfo(config.SectionGroups);
            ConfigurationSectionGroup group = config.SectionGroups["applicationSettings"];
            ClientSettingsSection section = group.Sections["Namespace.Properties.Settings"] as ClientSettingsSection;
            SettingElement sectionElement = section.Settings.Get("AllowedPlugins");

            SettingValueElement elementValue = sectionElement.Value;

The settings are a string collection and a string. like so:

<applicationSettings>
    <Namespace.Properties.Settings>
        <setting name="AllowedPlugins" serializeAs="Xml">
            <value>
                <ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
                    <string>Plugin1.Name</string>
                    <string>Plugin2.Name</string>
                    <string>Plugin3.Name</string>
                </ArrayOfString>
            </value>
        </setting>
        <setting name="blah" serializeAs="String">
            <value>sajksjaksj</value>
        </setting>
    </Namespace.Properties.Settings>
</applicationSettings>

I can create a string array from this in a bit of a kak handed way:

List<String> values = new List<string>(elementValue.ValueXml.InnerText.Split(new string[]{" ",Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries ));

but I wonder if there is a nice way that I'm missing that I can get my settings to be read and converted into objects of the right type in the same way that they are when the standard app.config file is read.

Please tell me there is...

Was it helpful?

Solution

The way that I've done this in the past is use a custom configuration section and implement an IConfigurationSectionHandler for the section. You still have to do all of the parsing inside the configuration section handler, but it makes it easy to get the information in the configuration section in the form you want it in your application. There is a How To article on MSDN that goes through the process of creating such a handler.

Below is an example of one that I've used:

usage:

Dictionary<string,AdministrativeRole> roles
        = ConfigurationManager.GetSection("roles")
             as Dictionary<string,AdministrativeRole>;

web.config:

<configuration>
   <configSections>
      <section name="roles"
               type="com.example.RolesDefinitionHandler, com.example" />
   </configSections>
   <roles>
       <role name="Administrator" group="domain\group-name" />
       ...
   </roles>
</configuration>

code:

public class RolesDefinitionHandler : IConfigurationSectionHandler
{
    private static readonly string ROLE_SECTION_NAME = "role";
    private static readonly string ROLE_SECTION_NAME_ATTRIBUTE = "name";
    private static readonly string ROLE_SECTION_GROUP_ATTRIBUTE = "group";

    private Dictionary<string, AdministrativeRole> ReadConfiguration( XmlNode section )
    {
        Dictionary<string, AdministrativeRole> roles = new Dictionary<string, AdministrativeRole>();
        foreach (XmlNode node in section.ChildNodes)
        {
            if (node.Name.Equals( ROLE_SECTION_NAME, StringComparison.InvariantCultureIgnoreCase ))
            {
                string name = (node.Attributes[ROLE_SECTION_NAME_ATTRIBUTE] != null) ? node.Attributes[ROLE_SECTION_NAME_ATTRIBUTE].Value.ToLower() : null;
                if (string.IsNullOrEmpty( name ))
                {
                    throw new ConfigurationErrorsException( "missing required attribute " + ROLE_SECTION_NAME_ATTRIBUTE );
                }

                string group = (node.Attributes[ROLE_SECTION_GROUP_ATTRIBUTE] != null) ? node.Attributes[ROLE_SECTION_GROUP_ATTRIBUTE].Value.ToLower() : null;
                if (string.IsNullOrEmpty( group ))
                {
                    throw new ConfigurationErrorsException( "missing required attribute " + ROLE_SECTION_GROUP_ATTRIBUTE );
                }

                if (roles.ContainsKey( name ))
                {
                    throw new ConfigurationErrorsException( "duplicate " + ROLE_SECTION_NAME + " for " + name );
                }

                roles.Add( name, new AdministrativeRole( name, group ) );
            }
            else
            {
                throw new ConfigurationErrorsException( "illegal node " + node.Name );
            }
        }

        return roles;
    }

    #region IConfigurationSectionHandler Members

    public object Create( object parent, object configContext, System.Xml.XmlNode section )
    {
        return ReadConfiguration( section );
    }

    #endregion
}

OTHER TIPS

A better solution might be, which is similar to how sql connection strings are added to a app.config:

http://msdn.microsoft.com/en-us/library/system.configuration.configurationcollectionattribute.aspx

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top