C# : Custom configuration section
Generally when we develop applications using .NET, we use our app/web.config as a place where we expose certain settings to our application(s) (its even possible to encrypt it for those who dare or feel the higher calling to use it to store sensitive information).
Your config file will likely look something like this:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <appSettings> <add key="1" value="a" /> <add key="2" value="b" /> <add key="3" value="c" /> </appSettings> </configuration>
Next we'll wack a reference to the system.configuration assembly into our application, which will allow us to access our settings via the ConfigurationManager - like seen in the following image.
Now we can always simply use the general appSettings section to store some rudimentary settings, but what if we wish to create a separate appSettings section specific to our company for example?
In the following snippet we do exactly that, we add a new section called "Company.appSettings", using one of the default section handlers, observe:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <section name="Company.appSettings" type="System.Configuration.NameValueFileSectionHandler" /> </configSections> <Company.appSettings> <add key="1" value="a" /> <add key="2" value="b" /> <add key="3" value="c" /> </Company.appSettings> <appSettings /> </configuration>
Programmatically we'll access the newly added section like this:
NameValueCollection settings = ConfigurationManager.GetSection("Company.appSettings") as NameValueCollection; if (settings != null) { foreach (string key in settings) { Console.WriteLine("{0} : {1}", key, settings[key]); } }
An alternative to using notation like Company.appSettings is that you can instead separate your custom sections using the sectionGroup node like so:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <sectionGroup name="Company"> <section name="appSettings" type="System.Configuration.NameValueFileSectionHandler" /> </sectionGroup> </configSections> <Company> <appSettings> <add key="1" value="a" /> <add key="2" value="b" /> <add key="3" value="c" /> </appSettings> </Company> <appSettings /> </configuration>
Accessing the settings from code will look something like this:
NameValueCollection settings = ConfigurationManager.GetSection("Company/appSettings") as NameValueCollection;
This is obviously not the limit to the customization possibilities - you might have seen/used the following settings in your config file when setting up .NET for sending mail:
<system.net> <mailSettings> <smtp> <network host="smtp.somehost.net" /> </smtp> </mailSettings> </system.net>
It is quite easy to create our own custom section similar to what we see in the preceding snippet.
The following snippet will give you a quick idea on how to create your own custom section, note inherited classes ConfigurationSection and ConfigurationElement.
using System; using System.Configuration; namespace Sections { public class XSection : ConfigurationSection { [ConfigurationProperty("x", DefaultValue = false, IsRequired = false)] public Boolean X { get { return (Boolean)this["x"]; } set { this["x"] = value; } } [ConfigurationProperty("y")] public YElement Y { get { return (YElement)this["y"]; } set { this["y"] = value; } } } public class YElement : ConfigurationElement { [ConfigurationProperty("y1", DefaultValue = "value", IsRequired = false)] public String Y1 { get { return (String)this["y1"]; } set { this["y1"] = value; } } [ConfigurationProperty("y2", IsRequired = true)] public Int32 Y2 { get { return (Int32)this["y2"]; } set { this["y2"] = value; } } } }
The custom section will look something like this in your config file:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <section name="XSection" type="Sections.XSection, ConsoleApplication1" allowLocation="true" allowDefinition="Everywhere" /> </configSections> <XSection x="true"> <y y1="test1" y2="10" /> </XSection> </configuration>
In order to access the custom node from code, you need to do the following:
Sections.XSection xsection = ConfigurationManager.GetSection("XSection") as Sections.XSection; if (xsection != null) { Console.WriteLine(xsection.X); Console.WriteLine(xsection.Y.Y1); Console.WriteLine(xsection.Y.Y2); }
There is a lot of other options also available, like the configurationcollection attribute - which allows us to add collections as settings to our config files - be sure to read the additional reading at the bottom of the page.
Additional Reading:
http://msdn.microsoft.com/en-us/library/2tw134k3.aspx
http://msdn.microsoft.com/en-us/library/system.configuration.configurationcollectionattribute.aspx
Posted by - Christoff Truter
Date - 2011-02-12 13:17:21
Comments - 4
Date - 2011-02-12 13:17:21
Comments - 4
C# Design Pattern : Strategy
The strategy design pattern defines a means by which we decouple a family of related algorithms and make them interchangeable among one another within a required context.
The interchangeable bits are referred to as strategies, generally one would define a strategy by way of interface or abstract class e.g.
interface IStrategy { bool DoSomething(); } /* abstract class Strategy { abstract public bool DoSomething(); } */ class StrategyA : IStrategy { public bool DoSomething() { return true; } } class StrategyB : IStrategy { public bool DoSomething() { return true; } }
In the following snippet (console app) a strategy gets assigned according to what the user passed to the command-line - which represents our context.
class Context { private IStrategy _Strategy; public Context(IStrategy Strategy) { this._Strategy = Strategy; } public bool DoSomething() { return this._Strategy.DoSomething(); } } class Program { static void Main(string[] args) { Context ctx = ((args.Length > 0) && (args[0] == "a")) ? new Context(new StrategyA()) : new Context(new StrategyB()); ctx.DoSomething(); } }
It is rather obvious to imagine the usefulness of this pattern in the real world.
Imagine for a moment that we need to copy a file to a server somewhere, there is a few things (among others) to consider:
- Location of the server in relation to the file we want to copy, outside/inside our network?
- Available transfer methods ftp/http(soap)/ssh etc
If we implement the strategy pattern, we're basically going to decouple & handle these various scenarios using separate strategy classes - according to the context the program finds itself in (e.g. the app is outside the LAN - use FTP strategy), we'll know which strategy to use.
The beauty of this approach is that since its decoupled, the app doesn't need to have knowledge about the implementations of our strategies. When creating a strategy we simply need to implement the Strategy interface / abstract class and ensure that the behavior from our implementations are predictable.
The following snippet is an example of this ftp/local scenario, we've got a FTPStrategy and a LocalStrategy (its behavior might not be completely predictable e.g. error handling wise):
interface IStrategy { public void UploadFile(String fullname, String folder); } class FTPStrategy : IStrategy { public void UploadFile(string fullname, string folder) { FileInfo fileInfo = new FileInfo(fullname); Uri requestUri = new Uri(String.Concat("ftp://example.com", folder, "/", fileInfo.Name)); FtpWebRequest ftpRequest = (FtpWebRequest)FtpWebRequest.Create(requestUri); ftpRequest.Method = WebRequestMethods.Ftp.UploadFile; ftpRequest.Credentials = new NetworkCredential("username", "password"); using (Stream writer = ftpRequest.GetRequestStream()) { byte[] contents = File.ReadAllBytes(fullname); writer.Write(contents, 0, contents.Length); } } } class LocalStrategy : IStrategy { public void UploadFile(string fullname, string folder) { FileInfo fileInfo = new FileInfo(fullname); byte[] contents = File.ReadAllBytes(fullname); File.WriteAllBytes(String.Concat("c:", folder, "/", fileInfo.Name), contents); } }
In the following snippet the dev needs to tell the app via enum which strategy to use, it would probably make sense to rather detect which strategy is the most appropriate to use in context - instead of requiring the dev to specify strategy via enum, but hey ;)
class Context { private IStrategy _Strategy; public Context(Strategies strategy) { if (strategy == Strategies.FTP) { _Strategy = new FTPStrategy(); } else if (strategy == Strategies.Local) { _Strategy = new LocalStrategy(); } } public void UploadFile(string fullname, string folder) { this._Strategy.UploadFile(fullname, folder); } } enum Strategies { FTP, Local } class Program { static void Main(string[] args) { Context ctx = new Context(Strategies.FTP); ctx.UploadFile(@"c:\somefolder\xls.xml", "/Skool"); } }
Incidently I recently used this pattern in one of my PHP projects, have a look over here.
Additional Reading
http://www.dofactory.com/Patterns/PatternStrategy.aspx
http://www.netobjectives.com/PatternRepository/index.php?title=TheStrategyPattern
Posted by - Christoff Truter
Date - 2011-02-10 17:10:41
Comments - 0
Date - 2011-02-10 17:10:41
Comments - 0
First 6 7 8 9 10 11 12 13 14 15 Last / 65 Pages (129 Entries)