Yes I know the above probably doesn’t make much sense when first read. But the truth is that in any convention based system, there is going to be some configuration, we can’t avoid it completely.
I’ve been working with using XAML as a configuration method in a convention based application where we had the requirement to pull in some details about where the from line in emails would come from.
Why use XAML? XAML enables us to control the structure of our configuration easily and it also gives us intellisense. If you’ve ever tried creating custom configuration sections for the web.config and and app.config files you’ll see where I am coming from here.
As part of my investigation into the problem I came across this really cool article on The Code Project called Using XAML for Custom Application Configuration which I used as part of my solution. The article goes into detail about XAML configuration in your application all I did was slightly adapt how I used what is here so it may be worth you reading this first to familiarise yourself with XAML configuration.
So how does it work?
As we were using dependency injection in our application I decided to inject my configuration into my classes. In this case by configuration class is based on the interface IBaseConfiguration.
1: namespace TestApplication
2: { 3: public class EmailManagement : IEmailManagement
4: { 5: private readonly IBaseConfiguration _configuration;
6:
7: public MyTestClass(IBaseConfiguration configuration)
8: { 9: _configuration = configuration;
10: }
11:
12: public void SendEmailToCustomer()
13: { 14: var emailSettings = this._configuration.GetConfiguration<ReplyEmailSettings>();
15:
16: var message = new MailMessage();
17:
18: message.From = new MailAddress(emailSettings.EmailAddress, emailSettings.Name);
19:
20: ...
21: ....
22: }
23: }
24: }
The main line to pay attention to above is line 14. See how I’ve used a generic to tell my configuration method I want the settings for the XAML configuration based on ReplyEmailSettings? Now lets take a look at the actual configuration class.
1: namespace TestApplication.Configuration
2: { 3: public class ConfigurationBase : IBaseConfiguration
4: { 5: /// <summary>
6: /// Get a configuration.
7: /// </summary>
8: /// <typeparam name="T">Type we want returned
9: /// </typeparam>
10: /// <returns>
11: /// A populated type
12: /// </returns>
13: public T GetConfiguration<T>()
14: { 15: Type itemType = typeof(T);
16: var pathbuilder = new StringBuilder();
17:
18: pathbuilder.Append("../../configuration/"); 19: pathbuilder.Append(itemType.Name);
20: pathbuilder.Append(".xaml"); 21:
22: using (FileStream xamlStream = File.OpenRead(pathbuilder.ToString()))
23: { 24: return (T)System.Windows.Markup.XamlReader.Load(xamlStream);
25: }
26: }
27: }
28: }
As you can see in the configuration class above what I have done is incredibly simple. My configuration class assumes that all configurations are stored within a configuration folder in my application. It also assumes that I am going to name my XAML configuration files the same as the class I use to represent them (line 19). So my configuration method goes and looks for my XAML file and returns its configuration for me in line 22 and 24.
I really like how this has worked out. It gets around the issue of having to separately store the location of your configuration files in yet another configuration file or hard coding them into your application.
I’ve included the XAML configuration file and its accompanying class for reference below.
The ReplyEmailSettings.XAML file
1: <Entities:ReplyEmailSettings xmlns="clr-namespace:XamlConfig;assembly=XamlConfig"
2: xmlns:col="clr-namespace:System.Collections;assembly=mscorlib"
3: xmlns:Entities="clr-namespace:TestApplication.Configuration.Entities;assembly=TestApplication.Configuration"
4:
5: EmailAddress="test@test.com"
6: Name="The name of the email from"
7: SubjectLine="The subject line"
8: >
9:
10:
11:
12: </Entities:ReplyEmailSettings>
The ReplyEmailSettings class the above XAML file is based on.
1:
2: namespace TestApplication.Configuration.Entities
3: { 4: public class ReplyEmailSettings
5: { 6: public string Name { get; set; } 7:
8: public string EmailAddress { get; set; } 9:
10: public string SubjectLine { get; set; } 11:
12: }
13: }
* Apologies for the formatting of this blog article. The new blog styles appear to have destroyed my code view plug-in.