Taking a shot to simplify Configuration Section using

14 בינואר 2008

תגיות:
אין תגובות

 

Configuration sections are our ability as developers to interfere in the structure of our configuration file and add some custom value in it. Yoav Michaely (my team mate) and I tried to make the use of it a little simpler.

Our goals:
1) Make easy use of configuration section instance
2) To imitate the functionality of AppSetting of key value collection
3) Maybe get some extra functionality in the way – how knows…?

So let see out class declaration:

public abstract class ConfigurationSectionBase<CurrentClass> : ConfigurationSection

that would be our base configuration section class that will encapsulate some basic logic like instance initialization, type converting and more

public abstract class ConfigurationSingleSectionBase<CurrentClass> : ConfigurationSectionBase<CurrentClass>where CurrentClass : ConfigurationSingleSectionBase<CurrentClass>

t hat would be our single section class, which will get us the goals we define earlier. As you can see the generic class gets the derived class as it type

The last part that I am missing for handle the job is the configuration section name, which you usually supply hard coded. I decide to pass it as an attribute over deriving class, and there is it definition

public sealed class ConfigurationSectionAttribute : Attribute

which have only one property of SectionName

Let's see how we are using that mechanize, shell we.

[ConfigurationSection("TestSection")]
public class TestSection : ConfigurationSingleSectionBase<TestSection>
{
    [ConfigurationProperty("Prop1")]
    public string Prop1
    {
        get { return GetSectionValue<string>("Prop1"); }
    }

    [ConfigurationProperty("Prop2")]
    public int Prop2
    {
        get { return GetSectionValue<int>("Prop2"); }
    }
}

As you can see derived for out base class, add the attribute to indicate what my section name in config file and wrote some properties. As you can see I used GetSectionValue<T> method, which come from our ConfigurationSingleSectionBase class which heples to conver property to it correct type.

Now we have to register the section to our config file, the usual way,like this

As you can see we can add properties and some key value collection to our section definition. Now comes the interesting part, how would we access our section instance, as some of you will remember the way we are getting configuration section handlers is by writing code like following:

object section = ConfigurationManager.GetSection("MyCoolSectionName");
if (section != null)
    MyNewSection sec = (MyNewSection)section;
sec.Prop1;

This is not so nice code to write for every and each section, so what would we do? My answer is nothing!
Remember our derive class (TestSection) so let look what it has?

Two simple properties:
Instance – gives you that ability to access all the properties of the section.
Setting – key value collection, well you can guess what it does.

Now you can write code like this:

TestSection.Instance.Prop1;
TestSection.Settings["first"];

Not bad I think for folowing allmost the same steps of creating a configuration section. But wait there is more (I promised in 3rd point int our goads definition). Now let me take you one stap foraord. Let's say I have tree environments in my work, dev, test and prod. All three of them have common setting like whether to write a log or not, but also they have uniqe data like user name and password. I want to be able to handle all this in one simple configuration section.

Let see the solution – class definition:

public abstract class ConfigurationMuiltiSectionBase<CurrentClass, ConfigurationCollectionElementClass> : ConfigurationSectionBase<CurrentClass>
where CurrentClass : ConfigurationMuiltiSectionBase<CurrentClass, ConfigurationCollectionElementClass>

where ConfigurationCollectionElementClass : ConfigurationSingleSectionBase<ConfigurationCollectionElementClass>
that would be our multi section class. As you can see the generic class gets the derived class itself as it type and another class of type ConfigurationSingleSectionBase.

Now you can define something like this:

[ConfigurationSection("projectenv")]
public class ProjectEnv : ConfigurationSingleSectionBase<ProjectEnv>
{
    private const string Prop1Name = "Name";
    [ConfigurationProperty(Prop1Name)]
    public string Name
    {
        get { return GetSectionValue<string>(Prop1Name); }
    }

    private const string Prop2Name = "User";
    [ConfigurationProperty(Prop2Name)]
    public string User
    {
        get { return GetSectionValue<string>(Prop2Name); }
    }

    private const string Prop3Name = "Password";
    [ConfigurationProperty(Prop3Name)]
    public string Password
    {
        get { return GetSectionValue<string>(Prop3Name); }
    }
}

[ConfigurationSection("environments")]
public class Environments : ConfigurationMuiltiSectionBase<Environments, ProjectEnv>
{
    private const string Prop1Name = "IsWriteConfig";
    [ConfigurationProperty(Prop1Name)]
    public bool IsWriteConfig
    {
        get { return GetSectionValue<bool>(Prop1Name); }
    }

    private const string Prop2Name = "ActiveSystem";
    [ConfigurationProperty(Prop2Name)]
    public int ActiveSystem
    {
        get { return GetSectionValue<int>(Prop2Name); }
    }
} 

And add the following definition to the config file:

Now you we write

Environments.Settings[0].Name;

or

Environments.Settings[Environments.Instance.ActiveSystem].Name;

as you can see

The return type of our setting is now a list of our inner section.

That’s it. Here is the code. Play with it a little and let me know if you find it usably.

הוסף תגובה
facebook linkedin twitter email

כתיבת תגובה

האימייל לא יוצג באתר. שדות החובה מסומנים *