简体   繁体   中英

C# .Net 4.0 - Custom Configuration File with Attributes and sections

I know that this topic has been covered in a number of different Stackoverflow articles, and I have read about 30 of them to make sure that what I am doing matches up with those. It is (even fro the .Net 2.0, 3.0, and 4.0 version of the answers)

I am attempting to create a very simple (at least in my mind) configuration file with custom attributes on the sections, and then optional items within the sections. So, now to the code:

<?xml version="1.0" encoding="utf-8" ?>
<CustomSiteConfiguration>
    <Sites>
        <Site siteRoot="/Site US" name="SiteUS_en">
        </Site>
        <Site siteRoot="/Site Canada" name="SiteCanada_en">
        </Site>
        <Site siteRoot="/Partner" name="Partner_en">
            <siteSettings>
                <setting name="" value="" />
            </siteSettings>
            <JavaScriptBundles>
                <file name="" />
            </JavaScriptBundles>
            <CSSBundles>
                <file name="" />
            </CSSBundles>
        </Site>
    </Sites>
</CustomSiteConfiguration>

So, what you are looking at is a global Section of type Sites which contains multiple sections (CollectionElementCollections) of type Site . Site is defined by custom attributes on the item, as well as optional items within the section itself. So, siteSettings is optional, JavaScriptBundles is optional, and CSSBundles are also optional.

The C# Code is below:

For Sites

public class CustomGlobalSiteConfiguration : ConfigurationSection
{
    public CustomGlobalSiteConfiguration() { }

    [ConfigurationProperty("Sites")]
    [ConfigurationCollection(typeof(SitesCollection), AddItemName="Site")]
    public SitesCollection Sites
    {
        get
        {
            return (SitesCollection)base["Sites"];
        }
    }
}

For Site Collections

[ConfigurationCollection(typeof(SitesCollection), AddItemName="Site")]
public class SitesCollection : ConfigurationElementCollection
{
    // Constructor
    public SitesCollection() { }

    /*
    public CustomSiteConfiguration this[int index]
    {
        get { return (CustomSiteConfiguration)BaseGet(index); }
        set
        {
            if (BaseGet(index) != null)
            {
                BaseRemoveAt(index);
            }
                BaseAdd(index, value);
        }
    }   // end of public siteSetting this [int index]
     * */

    protected override object GetElementKey(ConfigurationElement element)
    {
        return ((CustomSiteConfiguration)element).name;
    }

    protected override ConfigurationElement CreateNewElement()
    {
        return new SitesCollection();
    }
}

For Site Definition

/**
 * Overarching structure of the Site Item
 **/
public class CustomSiteConfiguration : ConfigurationElement
{
    [ConfigurationProperty("siteRoot")]
    public String siteRoot
    {
        get
        {
            return (String)this["siteRoot"];
        }
        set
        {
            this["siteRoot"] = value;
        }
    }

    [ConfigurationProperty("name")]
    public String name
    {
        get
        {
            return (String)this["name"];
        }
        set
        {
            this["name"] = value;
        }
    }

    [ConfigurationProperty("siteSettings", IsRequired=false)]
    public CustomSiteSiteSettings siteSettings 
    { 
        get 
        { 
            return this["siteSettings"] as CustomSiteSiteSettings;
        }
    }

    [ConfigurationProperty("JavaScriptBundles", IsRequired = false)]
    public JavaScriptBundles javaSciptBundle
    {
        get
        {
            return this["JavaScriptBundles"] as JavaScriptBundles;
        }
    }


    [ConfigurationProperty("CSSBundles", IsRequired = false)]
    public CSSBundles cssBundle
    {
        get
        {
            return this["CSSBundles"] as CSSBundles;
        }
    }


}       // end of public class CustomSiteConfiguration : ConfigurationSection

For SiteSettings Definition

/**
 * Subsection - Site Settings
 **/ 
public class CustomSiteSiteSettings : ConfigurationElementCollection
{
    // Constructor
    public CustomSiteSiteSettings() { }

    public siteSetting this [int index]
    {
        get { return (siteSetting)BaseGet(index);  }
        set
        {
            if (BaseGet(index) != null)
            {
                BaseRemoveAt(index);
            }
                BaseAdd(index, value);
        }
    }   // end of public siteSetting this [int index]

    protected override object GetElementKey(ConfigurationElement element)
    {
        return ((siteSetting)element).name;
    }

    protected override ConfigurationElement CreateNewElement()
    {
        return new CustomSiteSiteSettings();
    }

}       // end of public class CustomSiteSiteSettings : ConfigurationSection

Site Setting Element

public class siteSetting : ConfigurationElement
{
    [ConfigurationProperty("name")]
    public String name
    {
        get
        {
            return (String)this["name"];
        }
        set
        {
            this["name"] = value;
        }
    }   // end of public String name

    [ConfigurationProperty("value")]
    public String value
    {
        get
        {
            return (String)this["value"];
        }
        set
        {
            this["value"] = value;
        }
    }   // end of public String value
}       // end of public class siteSetting : ConfigurationElement

I am leaving out the other items for space, but the other parts look the same. Basically, what is happening is, I am getting

Unrecognized attribute 'siteRoot'. Note that attribute names are case-sensitive.

Looking at everything, it appears that I should be fine, however, I think I may be doing too much and missing things. Any help with this would be greatly appreciated.

Thanks

I have figured out what was wrong with my code. I am going to provide the information below. I used the following article for help on tracking down some of the pieces: How to implement a ConfigurationSection with a ConfigurationElementCollection

I took the entire code base back to nothing and built it up from scratch. The XML is still the same

<?xml version="1.0" encoding="utf-8" ?>
<CustomSiteConfiguration>
<Sites>
        <Site siteRoot="/Site US" name="SiteUS_en">
        </Site>
        <Site siteRoot="/Site Canada" name="SiteCanada_en">
        </Site>
        <Site siteRoot="/Partner" name="Partner_en">
            <siteSettings>
                <setting name="" value="" />
            </siteSettings>
            <JavaScriptBundles>
                <file name="" />
            </JavaScriptBundles>
            <CSSBundles>
                <file name="" />
            </CSSBundles>
        </Site>
    </Sites>
</CustomSiteConfiguration>

So, first I started with the Sites Container

public class CustomSiteSettingsSection : ConfigurationSection
{
    [ConfigurationProperty("Sites")]
    [ConfigurationCollection(typeof(SiteCollection), AddItemName="Site")]
    public SiteCollection Sites
    {
        get
        {
            return (SiteCollection)base["Sites"];
        }
    }           // end of public SiteCollection Site
}               // end of public class CustomSiteSettings : ConfigurationSection { 

And then I added the SiteCollection for the Collection of Site Elements

public class SiteCollection : ConfigurationElementCollection
{
    // Constructor
    public SiteCollection() { }

    public SiteElement this[int index]
    {
        get { return (SiteElement)BaseGet(index);  }
        set
        {
            if (BaseGet(index) != null)
            {
                BaseRemoveAt(index);
            }
            BaseAdd(index, value);
        }
    }       // end of public SiteElement this[int index]

    protected override ConfigurationElement CreateNewElement()
    {
        return new SiteElement();
    }       // end of protected override ConfigurationElement CreateNewElement()

    protected override object GetElementKey(ConfigurationElement element)
    {
        return ((SiteElement)element).name;
    }
}           // end of public class SiteCollection : ConfigurationElementCollection

Then I added the definition for the Site with optional values

public class SiteElement : ConfigurationElement
{
    // Constructor
    public SiteElement() { }

    [ConfigurationProperty("name", IsRequired = true, IsKey = true)]
    public String name
    {
        get { return (String)this["name"]; }
        set { this["name"] = value; }
    }           // end of public String name

    [ConfigurationProperty("siteRoot", IsRequired = true)]
    public String siteRoot
    {
        get { return (String)this["siteRoot"]; }
        set { this["siteRoot"] = value; }
    }           // end of public String siteRoot

    [ConfigurationProperty("siteSettings", IsRequired=false)]
    [ConfigurationCollection(typeof(SiteSettingsElementCollection), AddItemName = "setting")]
    public SiteSettingsElementCollection siteSettings
    {
        get
        {
            return (SiteSettingsElementCollection)base["siteSettings"];
        }
    }           // end of public SiteCollection Site
}               // end of public class SiteElement : ConfigurationElement

Next I added the SiteSettings Collection

public class SiteSettingsElementCollection : ConfigurationElementCollection
{
    // Constructor
    public SiteSettingsElementCollection() { }

    public SiteSettingElement this[int index]
    {
        get { return (SiteSettingElement)BaseGet(index); }
        set
        {
            if (BaseGet(index) != null)
            {
                BaseRemoveAt(index);
            }
            BaseAdd(index, value);
        }
    }       // end of public SiteElement this[int index]

    protected override ConfigurationElement CreateNewElement()
    {
        return new SiteSettingElement();
    }       // end of protected override ConfigurationElement CreateNewElement()

    protected override object GetElementKey(ConfigurationElement element)
    {
        return ((SiteSettingElement)element).name;
    }
}           // end of public class SiteCollection : ConfigurationElementCollection

And finally, I added the Setting Element Definition

public class SiteSettingElement : ConfigurationElement
{
    public SiteSettingElement() { }

    [ConfigurationProperty("name", IsRequired=true, IsKey=true)]
    public String name
    {
        get { return (String)this["name"]; }
        set { this["name"] = value; }
    }           // end of public String name

    [ConfigurationProperty("value", IsRequired = true)]
    public String value
    {
        get { return (String)this["value"]; }
        set { this["value"] = value; }
    }           // end of public String value
}               // end of public class SiteSettingElement : ConfigurationElement

At this point, I just repeat the same for the two bundles. In the end this all works, and allows for optional settings and sections.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM