Extension methods: If you have a shiny new hammer

March 20, 2009 at 10:40 AMAndre Loker

If you have a shiny new hammer, every problem looks like a nail they say. Although C# 3.0 extension methods are not that new anymore, this saying still applies. I ran across the announcement of the Generic Extension Methods Project. While I think a repository of useful extension methods sounds like a cool idea, one piece of code in that said announcement made me smile slightly:

   1: // IsNotNull is an extension method
   2: if(row.IsNotNull())
   3: {
   4:     row["First Column"] = "some value";
   5: }

Call me old fashioned, but I personally prefer the good old null-check a lot:

   1: // Pure and simple
   2: if(row != null)
   3: {
   4:     row["First Column"] = "some value";
   5: }

something != null  is an expression every developer understands. If I don’t know about extension methods or don’t know in particular that IsNotNull() is an extension method, I’d ask myself: “What does a method IsNotNull() do? Is nullness meant to be something different here? It has to, because calling a method on a null-variable would cause a NullReferenceException, wouldn’t it?”.

One inherent semantic of C# is that if you call a method on a null reference, it will crash. IsNotNull() is therefore completely counterintuitive. Either you force the reader to consider the possibility that the method might be an extension method and therefore you could call that method on null. Or you help those readers by preceding all usages of IsNotNull() with comments like “Note, this is an extension method”. Yuck!

But maybe this IsNotNull() implementation does a bit more for DataTableRows than just checking them to be not null. If it does, it’s name is misleading.

So you see: using IsNotNull() adds nothing but confusion to the code.

My personal recommendations regarding extension methods:

  • Don’t use them just because you can.
    • The ultimate goal should be to write simple, readable, comprehensible code. If an extension method helps – use it. If it doesn’t or is even counterproductive – don’t!
  • If there is a simpler concept built into the language, prefer that over extension methods. Some (partly far-fetched) examples:
    • prefer something != null over something.IsNotNull()
    • prefer if(something)… over if(something.IsTrue())…
    • prefer x = a + 1 over x = a.PlusOne()

A brief review

That being said, here’s a brief review of the extension methods that are found in the project as of now:

CollectionExtensions

FirstItem returns the first item of a list or array or null if there is no such item. Isn’t that what FirstOrDefault already does?

ReflectionExtensions

CreateInstance – which extends Type - comes in two flavours:

The first one tries to create an instance using the default constructor:

   1: public static T CreateInstance<T>(this System.Type type) where T : new()

Although the documentation says that you could use it like “typeof(MyObject).CreateInstance()” this is not true – you need to provide something for T. Not only do you need to provide the type twice (as the extended object and as T), you also end up with possible constructs like:

   1: typeof(string).CreateInstance<Version>();

This happily creates an instance of Version. What’s the use of extending Type then? Just use Activator – it’s simple and works:

   1: Activator.CreateInstance<Version>()

The other overload of CreateInstance additionally allows for constructor arguments being passed. What’s been said above still counts, typeof(string).CreateInstance<Version>(1,2,3,4) is awkward.

Just as a side note: what’s the use of a generic object creation method anyway? The documentation of Activator.CreateInstance<T> puts it nicely:

In general, there is no use for the CreateInstance in application code, because the type must be known at compile time. If the type is known at compile time, normal instantiation syntax can be used.

That is: if somewhere in the code I am able to say Activator.CreateInstance<Foo>() – why don’t I just say new Foo() in the first place? What I’d find more useful is something like this:

   1: public static T InstantiateAs<T>(this Type type) {
   2:   return (T) type.Instantiate();
   3: }
   4:  
   5: public static object Instantiate(this Type type) {
   6:   return Activator.CreateInstance(type);
   7: }

So you could say:

   1: Type type = ReadSomeTypeFromConfig(); // returns e.g. typeof(ServiceImpl)
   2: IService myService = type.InstantiateAs<IService>();

And likewise add overloads that accept constructor arguments.

ValidationExtensions

This class contains extension methods such as IsNull or IsNotNull – which I don’t like at all as explained above.

Additionally, you’ll find assertion methods like

   1: public static void AssertParameterNotNull(this object value, 
   2:                                           string message, 
   3:                                           string name)

It’s probably a matter of taste whether you like it or not. Again, I prefer a more explicit way. I prefer not to allow method calls on possible null-values and go with:

   1: Assert.ArgumentIsNotNull(theArgument, "theArgument", "Boy, that arg can't be null!")

Then we have AssertEquals which is supposed to be used like this:

   1: someValue.AssertEquals<MyException>(someOtherValue, "Some message");

That is, MyException is thrown if someValue does not equal someOtherValue. I can’t help it, it feels weird.

Next one:

   1: public static bool IsEmpty(this string value)
   2: public static bool IsNotEmpty(this string value)

Looks reasonable, doesn’t it? The problem with these methods is that their names are very misleading:

   1: /// <summary>
   2: /// Tests if the string is empty.
   3: /// </summary>
   4: /// <param name="value">The string to test.</param>
   5: /// <returns>True if the string is empty.</returns>
   6: public static bool IsEmpty(this string value)
   7: {
   8:     return value.Trim().Length == 0;
   9: }
  10:  
  11: /// <summary>
  12: /// Tests if the string is not empty.
  13: /// </summary>
  14: /// <param name="value">The string to test.</param>
  15: /// <returns>True if the string is not empty.</returns>
  16: public static bool IsNotEmpty(this string value)
  17: {
  18:     return value.Trim().Length > 0;
  19: }

According to those methods, “    “.IsEmpty() == true. Which is confusing because string.IsNullOrEmpty(“    “) returns false. I’d heavily suggest to rename those methods and be clear about the behaviour in the documentation.

Finally, there are a bunch of methods called IsEmpty and IsNotEmpty that work on different collection types (why aren’t they placed in the CollectionExtensions class?). While I find those methods useful there is an extreme amount of duplication. All those methods can be covered by these to little guys:

   1: public static bool IsEmpty<T>(this T collection) where T : ICollection {
   2:   return collection.Count == 0;
   3: }
   4:  
   5: public static bool IsNotEmpty<T>(this T collection) where T : ICollection {
   6:   return !collection.IsEmpty();
   7: }

Because all of the types handled in the library (ICollection, ICollection<T>, IList, IList<T>, IDictionary, IDictionary<K, T>, Array) inherit ICollection. Why did I make IsEmpty generic instead of just passing an ICollection? It’s just a little trick: if for whatever reason you have a value type that implements ICollection invoking IsEmpty(ICollection) on it would cause it to be boxed to treat it as an ICollection. By making IsEmpty generic with a constrained this boxing will not occur. OK, it’s not likely to happen, but I prefer this style. It explicitly says: “It operates on everything that can behave like an ICollection” rather than “It operates on an ICollection”. Sometimes it’s in the details.

Posted in: C# | Patterns

Tags: ,

Simple AOP: integrating interceptors into Windsor

February 20, 2009 at 3:47 PMAndre Loker

Aspect oriented programming (AOP) allows us to keep implement different concerns in isolation. In this article series I’ll describe ways to make use of AOP without much hassle. In the previous article of this serious we learned how to intercept method invocations using DynamicProxy2 and IInterceptors. However, we had to create the proxy instances manually. If you use Castle Windsor you can let the IoC container create the proxies and inject the interceptors.

I assume that you have used Castle Windsor or a different IoC container before. If not, check why you should use dependency injection.

Luckily Windsor integration of IInterceptors is a snap. In fact, you don’t have to add anything, it’s already been built in, because it has proven to be very useful. Because Windsor controls the instantiation of the registered components it was a logical consequence to add optional proxy creation and interface injection into that process. The Castle people are know what they do!

Basically, Windsor offers three ways to define interceptors that you want it to inject into components, ranging from rather static to fully dynamic.

Static injection with attributes

If all you want is the separation of concerns that injectors offer you and know which classes those aspects need to be applied to you can simply use the InterceptorAttribute.

Let’s start with a simple service interface and its implementation:

   1: public interface IService {
   2:     void DoSomething();
   3: }
   4:  
   5: public class Service : IService {
   6:     public void DoSomething() {
   7:         Console.WriteLine("Doing something");
   8:         throw new InvalidOperationException("Some exception thrown in DoSomething");
   9:     }
  10: }

And here’s the code that sets up Windsor for this service and creates an instance.

   1: var container = new WindsorContainer();
   2: container.Register(
   3:     Component.For<IService>().ImplementedBy<Service>()
   4: );
   5:  
   6: var service = container.Resolve<IService>();
   7: service.DoSomething();

As expected, running this piece of code will print “Doing something” and than fail with an uncaught exception. Now let’s say we want to add an aspect to the code that – in this simple case – prints a message to the console whenever an intercepted method throws an exception. Here’s the simple exception handling aspect from the previous article, which catches exception, prints an information message and optionally re-throws it.

   1: public class ExceptionAspect : IInterceptor {
   2:     public bool EatAll { get; set; }
   3:  
   4:     public void Intercept(IInvocation invocation) {
   5:         try {
   6:             invocation.Proceed();
   7:         } catch (Exception e) {
   8:             Console.WriteLine("{0} caught: {1}", e.GetType(), e.Message);
   9:             if (!EatAll) {
  10:                 throw;
  11:             }
  12:         }
  13:     }
  14: }

 

 

Two automatically inject this aspect into the Service component you only need to add two minor modifications:

1. Register the ExceptionAdvice as a component:

   1: container.Register(
   2:     Component.For<ExceptionAspect>()
   3:     .Parameters(Parameter.ForKey("EatAll").Eq("true"))
   4: );

 

2. Add the Castle.Core.InterceptorAttribute to the Service component:

   1: [Interceptor(typeof(ExceptionAspect))]
   2: public class Service : IService{
   3:     public void DoSomething() {
   4:         Console.WriteLine("Doing something");
   5:         throw new InvalidOperationException("Some exception thrown in DoSomething");
   6:     }
   7: }

This will tell Windsor to automatically create a proxy for the Service component and inject the interceptor of the given type (ExceptionAspect). Running the code now leads to the expected output:

image

Instead of a type you can also provide the key of a component to the InterceptorAttribute.

Simple dynamic injection

 

 

 

If you cannot or don’t want to use attributes – e.g. because you need to disable or enable certain aspects during configuration time – you can of course configure the Windsor container manually.

Let’s add a second aspect, namely a simple logging aspect that prints a message before and after the execution of intercepted methods. This is what our aspect looks like:

   1: public class LoggingAspect : IInterceptor {
   2:     public void Intercept(IInvocation invocation) {
   3:         Console.WriteLine("SomeInterceptor: Before method");
   4:         try {
   5:             invocation.Proceed();
   6:         } finally {
   7:             Console.WriteLine("SomeInterceptor: After method");
   8:         }
   9:     }
  10: }

Now we need to tell Windsor to inject the LoggingAspect into our Service. As with the ExceptionAspect we need to register the advice as a component:

   1: container.Register( Component.For<LoggingAspect>() );

Now we only need to change the registration of the service to inlcude the given aspect:

   1: container.Register(
   2:     Component
   3:     .For<IService>()
   4:     .ImplementedBy<Service>()
   5:     .Interceptors(InterceptorReference.ForType<LoggingAspect>()).Anywhere
   6: );

 

The only change is shown in line 5. The Interceptors() method expects an array of interceptors to apply to the component, Anywhere tells Windsor that we are not interested in the order in which multiple interceptors are applied (see below).

Running the application now yields:

image

 

If you configure the container in source code as shown above you can decide at configuration time which interceptors to inject. Of course, the interceptors can also be configured using an external XML file for full configurability.

If you configure multiple interceptors sometimes the order in which they are applied does matter. For example, assume you have an interceptor that caches method results and another one that secures the method for authorized access. In this case you will want the security interceptor to be applied before the caching interceptor, otherwise unauthorized user might see cached values that they are not allowed to see.  Windsor allows you to explicitly state the relative or absolute order of the configured interceptors.

  • ...Interceptors(interceptors).First
    The defined interceptors are prepended to the current list of interceptors.
  • ...Interceptors(interceptors).Last
    The defined interceptors are append to the current list of interceptors.
  • ...Interceptors(interceptors).AtIndex(x)
    The defined interceptors are inserted at the given index of the current list of interceptors.
  • ...Interceptors(interceptors).Anywhere 
    You don’t care where the interceptors are added.

Fully dynamic injection

You can even go one step further. Instead of defining the interceptors explicitly for the different components, Windsor allows you to install a hook that allows you to define the interceptors for each component on the fly during creation.

You can install that hook by implementing the interface IModelnterceptorsSelector which exposes two methods:

   1: public interface IModelInterceptorsSelector {
   2:     bool HasInterceptors(ComponentModel model);
   3:     InterceptorReference[] SelectInterceptors(ComponentModel model);
   4: }

Before a component is activated, Windsor calls HasInterceptor with the component model. If it returns true Windsor will invoke SelectInterceptors to request the actual interceptor references.

As an exammple, we’ll use another interceptor – TransactionAspect – that is injected with an IModelInterceptorSelector. First, here’s the interceptor:

   1: public class TransactionAspect : IInterceptor {
   2:     public void Intercept(IInvocation invocation) {
   3:         try {
   4:             Console.WriteLine("Opening transaction");
   5:             invocation.Proceed();
   6:             Console.WriteLine("Commit");
   7:         } catch (Exception e) {
   8:             Console.WriteLine("Rollback");
   9:             throw;
  10:         }
  11:     }
  12: }

And here’s our implementation of the IModelInterceptorsSelector:

   1: public class MyInterceptorSelector : IModelInterceptorsSelector {
   2:     public bool HasInterceptors(ComponentModel model) {
   3:         return typeof(TransactionAspect) != model.Implementation &&
   4:             model.Implementation.Namespace.StartsWith("SimpleAopWindsor");
   5:     }
   6:  
   7:     public InterceptorReference[] SelectInterceptors(ComponentModel model) {
   8:         return new[] { InterceptorReference.ForType<TransactionAspect>() };
   9:     }        
  10: }

As you see there’s nothing fancy going on here. HasInterceptors returns true for types in the SimpleAopWindsor namespace that are not TransactionAspect. The check for TransactionAspect is required in this specific case to prevent infinite recursion – otherwise, the TransactionAspect interceptor would be applied to itself.

SelectInterceptors simply returns an array of InterceptorReferences: in this case it contains only one element, ie. a reference to TransactionAspect.

Of course, we need to register the TransactionAspect as a component in Windsor:

   1: container.Register(
   2:     Component.For<TransactionAspect>()                
   3: );

And finally, we need to tell Windsor to use our interceptors selector.

   1: container.Kernel.ProxyFactory.AddInterceptorSelector(
   2:     new MyInterceptorSelector()
   3: );

If we run the application now we’ll see this:

image

What’s important here is the fact that our LoggingAspect and ExceptionAspect seem to be gone. This is important: if IModelInterceptorsSelector.SelectInterceptors returns a non-null array, only those interceptor will be used. Interceptors configured using one of the previously described methods (attributes or registration) will be ignored. If we want those interceptors to be applied as well our IModelnterceptorsSelector needs to return those references explicitly, eg. like this:

   1: public InterceptorReference[] SelectInterceptors(ComponentModel model) {
   2:     var interceptors = new List<InterceptorReference>(model.Interceptors.Count + 1);
   3:     // add all interceptors configured otherwise
   4:     foreach (InterceptorReference inter in model.Interceptors) {
   5:         interceptors.Add(inter);
   6:     }
   7:     // add an additional interceptor
   8:     interceptors.Add(InterceptorReference.ForType<TransactionAspect>());
   9:     
  10:     return interceptors.ToArray();
  11: }

Now our application uses all interceptors:

image

Conclusion

As you’ve seen there are many different ways to inject inspectors into components in a Windsor container, ranging from static definition of inspectors using attributes to fully dynamic injection using IModelInterceptorsSelector.

What’s missing in comparison toclassic” AOP frameworks such as AspectJ? Pointcuts of course! With IModelInterceptorsSelector we are able to choose which types get interceptors applied, but those interceptors intercept every method of the target. We’d like to be able to define something similar to pointcuts to select the methods that get intercepted. And that’s what’s the next article in this series will be about. Stay tuned!

Souce code for this article: SimpleAopWindsor.zip (600.79 kb)

Previous articles:

Posted in: C# | Castle | Patterns

Tags: , ,

Subtle design: inheritance vs roles

February 10, 2009 at 11:04 AMAndre Loker

Let’s say you’re supposed to design a staff administration. Part of the domain model are managers and employees. Whenever you talk to your client you hear sentences such as “some of our employees are managers of a given department” or similar. Therefore, you might be tempted to model employees and managers as an “is-a” relationship, that is, you use inheritance.

isa

Let us evaluate this (really simple!) model critically. What implications does a design like this have, assuming that we are going to implement this model in a OO language like C#?

1. First of all, it implies that everyone is either an employee or a manager throughout his or her life. Although we can principally model “dynamic inheritance” in e.g. ERDs, in a language such as C# we can’t change the type of an instance all of a sudden. So, if you create a new employee, you’d have to decide whether it is in fact an employee or a manager and create an instance of the according type. As a consequence, an employee can’t be promoted to a manager and a manager can’t be degraded to a simple employee.

2. An employee can’t manage more than one department. Because one employee can’t be “multiple managers at once” (although some might which to when looking at their schedule *g*), there’s no way to let some employee manager multiple departments. Of course, in this simple model you could change the cardinality of the Manager <-> Departmennt relationship. But as soon as you for example want to assign a bonus payment to managers dependent on the manager itself and the department, simply associating multiple departments to a single manager won’t do the trick anymore.

By now you should have realized that modelling the employee-manager relationship as an “is-a” is rather inflexible. We can improve the design if we reconsider the meaning “some of our employees are managers of a given department”. What this actually means is: “some of our employees are in the role of being a manager of a given department”. Thus, being a manager is a role played by a player, ie. the employee. In general this can be modelled like:

role1As you see the player can play multiple roles, each role is played by only one player. We can easily attach or detach roles as needed without changing the type of the player. Putting the role-player relationship into our case leads to:

emproleThis design is much more flexible: employees can start as “normal” employees, can be promoted or degraded and can manage as many departments at once as required.

Identification and countability

When do you model a relationship as inheritance and when as a role-player relationship? To help you make this decision R. J. Wieringa (see references below) suggests to determine how the different entities are counted and how they are identified. If we count managers, do we count in fact employees? If so, each manager should be identified the same way as employees, e.g. by an employee number. In that case managers and employees can be modelled using inheritance. On the other hand, if managers are counted and identified differently from employees (e.g. using a management contract number) we should apply the role-player relationship.

Another example given by Mr Wieringa is the relationship between persons and passengers on a flight. Modelling passengers as a subtype of persons is probably not optimal because it would imply that a person can only be a passenger once. Passengers are most likely not counted as persons. They are probably identified by a ticket number not by e.g. a social security number.

Conclusion

Be critical if you model “obvious” is-a relationships. Do you really have a case of specialization or is the “subtype” only a role that is played by the general type?

References

Once again the concepts presented in this article are based on Design Methods for Reactive Systems by R.J. Wieringa (Amazon) (And no, I don’t get any commission for recommending this book).

Posted in: Design | Patterns

Tags: ,

Subtle design: snapshot cardinalities

February 9, 2009 at 3:02 PMAndre Loker

So your designing some application, let’s say for a library. Being the DDD guy that you are, you talk to a clerk at the library and she tells you that the system under development should save the fact that a book is lent out by a specific reader. So you choose to model that fact like this:

book You present this diagram to the library manager and he’s slightly confused: “What’s that? Our books are lent out by hundreds or thousands of people. Your design supports only one reader!”

You answer: “No, no. This model only says that a book is lent out by a single reader at a given time.

What happened here is that the library manager and you had a different idea of what portion of time the UML model represented. For you, the cardinalities shown in the diagram represented so called Snapshot Cardinalities, ie. cardinalities that occur at a single point in time. E.g. at any given moment, a book is lent by not more than one reader. The manager looked from a different perspective and interpreted the cardinalities as being historic. Throughout the lifetime of a book it is lent out by many readers, therefore his confusion.

The moral of the story

  • don’t assume that everyone looking at an UML diagram has the same idea of the semantics of numbers (or arrows for that matter).
  • be aware that we can have snapshot cardinalities as well as historic cardinalities. Most of the time you’ll use snapshot cardinalities because that’s what you’ll probably use in your code later on. Nevertheless, make that clear to the people with which you’re talking about the diagram
  • don’t mix different types of cardinalities, or be very explicit if you do so

For the interested reader I recommend R.J. Wieringa, Design Methods for Reactive Systems (Amazon)

Posted in: Patterns | Design

Tags: ,

Getting rid of strings (3): take your app settings to the next level

September 5, 2008 at 1:23 PMAndre Loker

In the previous parts of this series (part 1, part 2) I talked about the problems with literal strings in source code and presented different strategies to avoid those problems. In this episode I'll explain how we can abstract from app settings and leverage the power of the Castle DictionaryAdapter to improve the way our applications access their app settings.

Basics

Probably the easiest way to make certain aspects of a .NET application configurable is by using app settings. You can define app settings by adding (or augmenting) an <appSettings> section to your web.config or app.config, depending on the project type. This could look something like this:

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <configuration>
   3:   <appSettings>
   4:     <add key="MaxUsers" value="20"/>
   5:     <add key="FeedbackMail" value="foo@localhost"/>
   6:   </appSettings>
   7: </configuration>

[As a small side note: you don't have to physically keep the appSettings section in the web.config/app.config file - read Keep your .config clean with external config files to learn how to move settings outside of the config file.]

To access the settings easily use the configuration API exposed by ConfigurationManager, specifically the AppSettings property. Here's a tiny app that accesses the values from the appSettings section:

   1: using System;
   2: using System.Configuration;
   3:  
   4: public class Program {
   5:   private static void Main() {
   6:     string feedbackMail = ConfigurationManager.AppSettings["FeedbackMail"];
   7:     int maxUsers = int.Parse(ConfigurationManager.AppSettings["MaxUsers"]);
   8:     Console.WriteLine("Feedback e-mail address: {0}", feedbackMail);
   9:     Console.WriteLine("Max users: {0}", maxUsers);
  10:   }
  11: }

As you see, that's fairly simple. Some points of interest:

  • ConfigurationManager lives in System.Configuration. You need to add the assembly System.Configuration.dll to your project to use this class
  • AppSettings has two indexers:
    • One indexer accepts a string: the string provided should be one of the keys as defined in the appSettings section. The value returned is the content of the value attribute of the respective appSettings entry or null if the key wasn't found. Keys are case insensitive by the way, so AppSettings["feedbackMAIL"] returns the same value as AppSettings["FeedbackMail"]. Note, however, that white space before or after the key does count, so AppSettings[" FeedbackMail"] will return null. Also be sure to check your config file for accidentally added white space within the key attribute if your app does not find certain keys.
    • The other indexer accepts an integer, which is the index of the app setting to return. Granted, I don't see much use for that indexer.
  • The values returned by the indexers are always strings. Therefore, if you want to have an app setting as an integer you'll need to parse it.

Let's analyse this basic approach:

  • We use strings to index the AppSettings property which - as you should know by now - is very problematic.
    • If you misspell the key, the value returned is null, but you won't notice it before runtime.
    • If you change the key in the app settings, you'll have to update all references to that key in your code. Remember that strings are hard to refactor.
  • Values are always returned as strings so you need to parse them if you need data of a type other than string

Improving the situation

If you read the first article of this series you know that there are two basic steps that can improve the situation:

  1. Avoid spreading literals all over the code, define and use constants instead
  2. Hide any string dependent code behind an appropriate API

Applying those rules might lead you to the idea to write a class that encapsulates the app settings. A good idea indeed! Here's a class that encapsulates the app settings of our tiny example:

   1: class MySettings {
   2:   // constants that define the keys in the app settings
   3:   private const string MaxUsersKey = "MaxUsers";
   4:   private const string FeedbackMailKey = "FeedbackMail";
   5:  
   6:   public static string FeedbackMail {
   7:     get { return ConfigurationManager.AppSettings[FeedbackMailKey]; }
   8:   }
   9:  
  10:   public static int MaxUsers {
  11:     get { return int.Parse(ConfigurationManager.AppSettings[MaxUsersKey]); }
  12:   }
  13: }

I made the properties static because the class is stateless. Now you can access the settings like this:

   1: public class Program {
   2:   private static void Main() {
   3:     string feedbackMail = MySettings.FeedbackMail;
   4:     int maxUsers = MySettings.MaxUsers;
   5:     Console.WriteLine("Feedback e-mail address: {0}", feedbackMail);
   6:     Console.WriteLine("Max users: {0}", maxUsers);
   7:   }
   8: }

This is much better! The strings are neatly hidden, so is the parsing of the integer. You can refactor the names of the properties easily using the refactoring tool of your choice.

Is this solution the final answer? Certainly not. This solution still suffers from some issues :

  • It's tedious to add and implement properties and possible parsing manually for each setting in the app settings section.
  • The settings are now strictly tied to ConfigurationManager. It's difficult to mock some app settings for unit testing using this approach.

Let me elaborate on the second issue: assume you have a class that is responsible for sending an email to the system administrator in case of an error. Here's a possible excerpt of such a system:

   1: // an interface we use to abstract sending of emails.
   2: public interface IMailSender {
   3:   void Send(string to, string subject, string text);
   4: }
   5:  
   6: // Sends error reports by mail
   7: public class ErrorReporter {
   8:   private readonly IMailSender mailSender;
   9:  
  10:   public ErrorReporter(IMailSender mailSender) {
  11:     this.mailSender = mailSender;
  12:   }
  13:  
  14:   public void SendErrorReport(string text) {
  15:     var email = MySettings.FeedbackMail;
  16:     mailSender.Send(email, "Application error", text);
  17:   }
  18: }
  19:  

It's certainly nice that we did not hardcode the email address that the report is sent to. But if we were to unit test the method we'd have to provide a value for the FeedbackMail app setting. (I'm using Rhino Mocks by the way)

   1: [Test]
   2: public void SendErrorReport_UsesMailSender() {
   3:   var mailSender = MockRepository.GenerateMock<IMailSender>();
   4:  
   5:   var text = "test message";
   6:   var email = "foo@localhost";
   7:  
   8:   // need to inject the email into the app settings
   9:   ConfigurationManager.AppSettings["FeedbackMail"] = email;
  10:  
  11:   var reporter = new ErrorReporter(mailSender);
  12:   reporter.SendErrorReport(text);
  13:  
  14:   mailSender.AssertWasCalled(x=>x.Send(email, "Application error", text));
  15: }

To make the test work we need to inject the expected email address into the app settings. I personally think that this situation is awkward and does certainly not isolate the unit test around one class under test. ErrorReporter uses MySettings which again uses ConfigurationManager. For my taste the number of classes involved in this unit test is unnecessarily high.

A solution

If you've never heard of Castle DictionaryAdapter, go and read my article on it, because this little tool will improve our solution a lot.

Here's what we do:

  • Delete MySettings, we won't use it anymore
  • Create instead an interface that represents your app settings:
   1: public interface ISettings {
   2:   int MaxUsers { get; }
   3:   string FeedbackMail { get; }
   4: }
  • Create a dictionary adapter that handles all the plumbing between ISettings and AppSettings:
   1: var factory = new DictionaryAdapterFactory();
   2: var adapter = factory.GetAdapter<ISettings>(ConfigurationManager.AppSettings);
  • Use this object instead of MySettings:
   1: public class Program {
   2:   private static void Main() {
   3:     var factory = new DictionaryAdapterFactory();
   4:     var settings = factory.GetAdapter<ISettings>(ConfigurationManager.AppSettings);
   5:     var feedbackMail = settings.FeedbackMail;
   6:     var maxUsers = settings.MaxUsers;
   7:     Console.WriteLine("Feedback e-mail address: {0}", feedbackMail);
   8:     Console.WriteLine("Max users: {0}", maxUsers);
   9:   }
  10: }

Again, we have a type safe interface for our app settings. But what did we gain?

First we have to use much less code to define the interface for our app settings: ISettings is a no-brainer, just define properties with the desired type and the name matching the app settings key [see this article on DictionaryAdapter to learn how this can be configured in detail]. The DictionaryAdapter will handle all necessary lookup and conversion for you. Less code on our side is A Good Thing™.

Secondly by using an interface we have created a better abstraction of the app settings. Combine this with the power of dependency injection and you've created a basis for well testable, highly configurable code. If you don't see what I mean, read on and let me elaborate.

Why this solution rocks

First of all change ErrorReporter to accept an ISettings instance and use it instead of MySettings:

   1: public class ErrorReporter {
   2:   private readonly IMailSender mailSender;
   3:   private readonly ISettings settings;
   4:  
   5:   // Inject ISettings as well
   6:   public ErrorReporter(IMailSender mailSender, ISettings settings) {
   7:     this.mailSender = mailSender;
   8:     this.settings = settings;
   9:   }
  10:  
  11:   public void SendErrorReport(string text) {
  12:     var email = settings.FeedbackMail; // use ISettings instead of MySettings
  13:     mailSender.Send(email, "Application error", text);
  14:   }
  15: }

Two changes have taken place: I inject the ISettings dependency through the constructor and I use this object to access the email address.

ISettings in action - unit test

Here's the updated version of the unit test from above:

   1: [Test]
   2: public void SendErrorReport_UsesMailSender() {
   3:   var mailSender = MockRepository.GenerateMock<IMailSender>();
   4:  
   5:   var text = "test message";
   6:   var email = "foo@localhost";
   7:  
   8:   // create a stub for ISettings
   9:   var settings = MockRepository.GenerateStub<ISettings>();
  10:   // let this stub's FeedbackMail property return a specific value
  11:   settings.Stub(x => x.FeedbackMail).Return(email);
  12:  
  13:   // inject the settings
  14:   var reporter = new ErrorReporter(mailSender, settings);
  15:   reporter.SendErrorReport(text);
  16:  
  17:   mailSender.AssertWasCalled(x=>x.Send(email, "Application error", text));
  18: }

This approach is far superior to the old approach because we only have to stub a direct dependency of ErrorReporter (ie. ISettings). There's no need to configure an indirect dependency like ConfigurationManager.AppSettings. Furthermore we could now make an ISettings mock to check whether ErrorReporter really uses the settings object. Short, we have the full control of the behaviour of the ISettings instance.

ISettings in action - the real app

To use ISettings and ErrorReporter in a real app, we'd preferably use an IoC container like Castle Windsor to configure the ErrorReporter instance.

Here's how you could configure the container:

   1: var container = new WindsorContainer();
   2: // we'll need an implementation of IMailSender
   3: container.Register(Component.For<IMailSender>().ImplementedBy<SomeClassImplementingIMailSender>());
   4:  
   5: // create the adapter
   6: var adapter = new DictionaryAdapterFactory().GetAdapter<ISettings>(ConfigurationManager.AppSettings);
   7: // register this adapter instance as the component for ISettings
   8: container.Register(Component.For<ISettings>().Instance(adapter));
   9:  
  10: // and finally register the error reporter
  11: container.Register(Component.For<ErrorReporter>());

Whenever we need an instance of ErrorReporter now we can ask the container for it (object locator approach):

   1: var reporter = container.Resolve<ErrorReporter>();
   2: reporter.SendErrorReport("Something went horribly wrong");

Alternatively you could let the IoC container inject an ErrorReporter instance where you need it (dependency injection approach).

Both ways we'll get an ErrorReporter instance that is readily configured to access the app settings in a transparent way.

Conclusion

By using the proposed combination of

  1. an interface defining the app settings
  2. a dictionary adapter that maps between the AppSettings and the interface and
  3. an IoC container that can inject the adapter wherever we need it

we were able to completely get rid of any app settings related strings and created an architecture that is easily configurable and well testable.

By abstracting from the appSettings in the app.config file it's also easy to use a different configuration source instead. DictionaryAdapter can wrap all kinds of dictionaries and NameValueCollections. And if you come to the conclusion that you'd rather want to store the app settings in a database, it's easy to do, as well. Instead of using the DictionaryAdapter you could implement ISettings in a way that loads app settings from a database.

Posted in: C# | Patterns

Tags: , , , ,