Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I convert attribute to nested element?

I'm reading settings from 'App.config'. I just figured out how to work with ConfigurationSection, ConfigurationElementCollection and ConfigurationelElement.

App.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration> 
    <configSections>
        <sectionGroup name="notificationSettingsGroup">
                <section name="mailTemplates" type="Project.Lib.Configuration.MailTemplateSection, Project.Lib"
                    allowDefinition="Everywhere" allowExeDefinition="MachineToApplication" requirePermission="false"/>
        </sectionGroup>         
    </configSections>
    <notificationSettingsGroup>
        <mailTemplates>
            <items>
                <mailTemplate name="actionChain" subject="Subject bla-bla">
                    <body>Body bla-bla</body>
                </mailTemplate>                 
            </items>
        </mailTemplates>
    </notificationSettingsGroup>
    <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
    </startup>  
</configuration>

My C# code:

public class MailTemplateSection : ConfigurationSection
{
    [ConfigurationProperty("items", IsDefaultCollection = false)]
    public MailTemplateCollection MailTemplates
    {
        get { return (MailTemplateCollection)this["items"]; }
        set { this["items"] = value; }
    }
}

[ConfigurationCollection(typeof(MailTemplateElement), AddItemName = "mailTemplate",
    CollectionType = ConfigurationElementCollectionType.AddRemoveClearMap)]
public class MailTemplateCollection : ConfigurationElementCollection
{
    protected override ConfigurationElement CreateNewElement()
    {
        return new MailTemplateElement();
    }

    protected override object GetElementKey(ConfigurationElement element)
    {
        return ((MailTemplateElement) element).Name;
    }
}

public class MailTemplateElement : ConfigurationElement
{
    [ConfigurationProperty("name", DefaultValue = "action", IsKey = true, IsRequired = true)]
    public string Name
    {
        get { return (string)this["name"]; }
        set { this["name"] = value; }
    }

    [ConfigurationProperty("subject", DefaultValue = "Subject", IsKey = false, IsRequired = true)]
    public string Subject
    {
        get { return (string)this["subject"]; }
        set { this["subject"] = value; }
    }

    [ConfigurationProperty("body", DefaultValue = "Body", IsKey = false, IsRequired = true)]
    public string Body
    {
        get { return (string)this["body"]; }
        set { this["body"] = value; }
    }
}

And working code:

class Program
{
    static void Main(string[] args)
    {
        Configuration config =
            ConfigurationManager.OpenExeConfiguration(
            ConfigurationUserLevel.None);

        var mailTemplatesSection =
           config.GetSection("notificationSettingsGroup/mailTemplates") as MailTemplateSection;

    }
}

All works, when I'm declaring fields as attributes in xml. But when I try to convert attributes into nested element - "Property 'Body' is not a ConfigurationElement" error occurs.

What am I doing wrong?

like image 356
lewis Avatar asked Nov 25 '11 12:11

lewis


1 Answers

Because you have to create custom types and derive them from ConfigurationElement in order to use them as elements in config file. All simple types are always written as attributes. For example:

public class Body : ConfigurationElement
{
    [ConfigurationProperty("value", DefaultValue = "Body", IsKey = true, IsRequired = true)]
    public string Value{get;set;}
}

This will allow you to write

<body value="some val"/>

in your config.

like image 120
Vladimir Perevalov Avatar answered Oct 21 '22 13:10

Vladimir Perevalov