Strongly typed app settings with Castle DictionaryAdapter

A while ago (almost 4 years ago, to be precise) Ben Hall wrote a blogpost about using Castle DictionaryAdapter to build a simple, strongly typed wrapper aroud application settings.

While extremely simple, and gets the job done, there are a few ways it can be improved. With that, this blogpost can be treated as an introduction to Castle DictionaryAdapter (which sadly has precisely zero documentation).

While the apprpach is really simple, we’re going to take a detailed look and take it slowly, which is why this post is fairly long. Buckle up.

What is DictionaryAdapter

In a nutshell DictionaryAdapter is a simple tool to provide strongly typed wrappers around IDictionary<string , object>

Here’s a simple example:

// we have a dictionary...
var dictionary = new Dictionary<string, object>
{
	{ "Name", "Stefan" },
	{ "Age", 30 }
};

// ...and an adapter factory
factory = new DictionaryAdapterFactory();

// we build the adapter for the dictionary
var adapter = factory.GetAdapter<IPerson>(dictionary);

Debug.Assert(adapter.Name == "Stefan");

Wrapping app settings

While the project is called DictionaryAdapter in fact it can do a bit more than just wrap dictionaries (as in IDictionary). It can be used to wrap XmlNodes or NameValueCollections like Configuration.AppSettings and this last scenario, is what we’re going to concentrate on.

The goals

We’ve got a few goals in mind for that project:

  • strongly typed – we don’t want our settings to be all just strings
  • grouped – settings that go together, should come together (think username and password should be part of a single object)
  • partitioned – settings that are separate should be separate (think SQL database connection string and Azure service bus url)
  • fail fast – when a required setting is missing we want to know ASAP, not much later, deep in the codebase when we first try to use it
  • simple to use – we want the junior developer who joins the team next week to be able to use it properly.

With that in mind, let’s get to it.

Getting started

DictionaryAdapter lives in Castle.Core (just like DynamicProxy), so to get started we need to get the package from Nuget:

Install-Package Castle.Core

Once this is done and you’re not using Resharper make sure to add using Castle.Components.DictionaryAdapter; to make the right types available.

The config file

Here’s our config file, we’ll be dealing with. Notice it follows a simple naming convention with prefixes to make it easy to group common settings together. This is based on a real project.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <appSettings>
    <add key="environment-type" value="Local" />
    <add key="environment-log-minimum-level" value="Debug" />
    <add key="auth0-client-id" value="abc123abc" />
    <add key="auth0-client-secret" value="123abc123abc" />
    <add key="auth0-domain" value="abc123.auth0.com" />
    <add key="auth0-database-connection-name" value="ABC123" />
    <add key="auth0-token-expiration-seconds" value="3600" />
  </appSettings>
</configuration>

As you can see we have two sets of settings here. One for general environment configuration, and another one for integration with Auth0.

Config interfaces

Now let’s proceed to creating our interfaces, exposing the configuration values to our application. We follow a naming convention where the name of config value corresponds to type/property on the interface. This makes it trivial to see which config value maps to which property on which interface.

For clarity I’d also recommend putting the interfaces in a designated namespace, like MyApp.Configuration.

public interface IEnvironment
{
    EnvironmentType Type { get; }
    LogEventLevel LogMinimumLevel { get; }
}

public interface IAuth0
{
    string ClientId { get; }
    string ClientSecret { get; }
    string Domain { get; }
    string DatabaseConnectionName { get; }
    int TokenExpirationSeconds { get; }
}

Having the interfaces and the config we can start writing the code to put the two together

Bare minimum

Let’s rewrite the code from the beginning of the post to use our config file and interfaces. If you’re not using Resharper you’ll have to manually add a reference to System.Configuration.dll for the following to work.

var factory = new DictionaryAdapterFactory();

var environment = factory.GetAdapter<IEnvironment>(ConfigurationManager.AppSettings);

Debug.Assert(environment.Type == EnvironmentType.Local);

If we run it now, we’ll get a failure. DictionaryAdapter doesn’t know about our naming convention, so we have to teach it how to map the type/property to a config value.

Implementing DictionaryBehaviorAttribute

There are two ways to customise how DictionaryAdapter operates.

  • Transparent, using an overload to GetAdapter and passing a PropertyDescriptor with customisations there.
  • Declarative, using attributes on the adapter interfaces to specify the desired behaviour. If you’ve used Action Filters in ASP.NET MVC, it will feel familiar.

In this example we’re going to use the latter. To begin, we need to create a new attribute, inheriting from DictionaryBehaviorAttribute, and apply it to our two interfaces

public class AppSettingWrapperAttribute : DictionaryBehaviorAttribute, IDictionaryKeyBuilder
{
    private readonly Regex converter = new Regex("([A-Z])", RegexOptions.Compiled);

    public string GetKey(IDictionaryAdapter dictionaryAdapter, string key, PropertyDescriptor property)
    {
        var name = dictionaryAdapter.Meta.Type.Name.Remove(0, 1) + key;
        var adjustedKey = converter.Replace(name, "-$1").Trim('-');
        return adjustedKey;
    }
}

We create the attribute and implement IDictionaryKeyBuilder interface, which tells DictionaryAdapter we want to have a say at mapping the property to a proper key in the dictionary. Using a trivial regular expression we map NameLikeThis to Name-Like-This.

Having done that, if we run the application again, the assertion will pass.

Fail Fast

If we remove the environment-log-minimum-level setting from the config file, and run the app again, it will still pass just fine. In fact, since LogEventLevel (which comes from Serilog logging framework) in an enum, therefore a value type, if we read the property everything will seem to have worked just fine. A default value for the enum will be returned.

This is not the behaviour that we want. We want to fail fast, that is if the value is not present or not valid, we want to know. To do it, we need two modifications to our AppSettingWrapperAttribute

Eager fetching

First we want the adapter to eagerly fetch values for every property on the interface. That way if something is wrong, we’ll know, even before we try to access the property in our code.

To do that, we implement one more interface – IPropertyDescriptorInitializer. It comes with a single method, which we implement as follows:

public void Initialize(PropertyDescriptor propertyDescriptor, object[] behaviors)
{
    propertyDescriptor.Fetch = true;
}

Validating missing properties

To ensure that each setting has a value, we need to insert some code into the process of reading the values from the dictionary. To do that, there is another interface we need to implement: IDictionaryPropertyGetter. This will allow us to inspect the value that has been read, and throw a helpful exception if there is no value.

public object GetPropertyValue(IDictionaryAdapter dictionaryAdapter, string key, object storedValue, PropertyDescriptor property, bool ifExists)
{
    if (storedValue != null) return storedValue;
    throw new InvalidOperationException(string.Format("App setting \"{0}\" not found!", key.ToLowerInvariant()));
}

If we run the app now, we’ll see that it fails, as we expect, telling us that we forgot to set environment-log-minimum-level in our config file.

Wrapping up

That’s it. Single attribute and a minimal amount of bootstrap code is all that’s needed to get nice, simple to use wrappers around application settings.

Additional bonus is, that this is trivial to integrate with your favourite IoC container.

All code is available in this gist.

How to force Nuget not to update log4net to 1.2.11

That’s a quick one. There’s been a new release of log4net recently that’s signed with a new key, and therefore is incompatible with old version 1.2.10.

Therefore, due to near-ubiquity of the library in .NET space, it may cause some problems if you happen to have a dependency (direct or indirect) on it.

The matters are made worse by Nuget’s default of getting the latest available version of the package. I dealt with this problem the other day, and I saw a few people in my twitter stream struggling with the same issue.

The solution is quite simple. It’s not specific to log4net and I’m not picking on log4net here. Here’s how you can restrict Nuget’s package to specific version in your solution.

 

So imagine you install a package that has a dependency on log4net. In this case, the dependency is specified as specifically version 1.2.10 (as opposed to Nuget’s default: this version of newer).

nuget_core

If after that we install another package that also depends on log4net but doesn’t restrict the version, we’ll have a problem.

nuget_log4net_fail

The package we were trying to install doesn’t get installed. Actually, even if it did, we would have a problem since it most likely was compiled against log4net 1.2.10 anyway, and if Nuget updated log4net to version 1.2.11 the app would throw an exception at runtime due to mismatched assembly.

So there is a solution to restrict version of the package to specific version (in this case 1.2.10) as specified in the documentation.

nuget_log4net_fail_solution

After adding allowedVersions=”[1.2.10]” we can try again and this time the package will install properly.

nuget_log4net_fail_avoided

Notice it says it installed log4net 1.2.11. I checked my packages folder, and project dependencies and the version referenced was 1.2.10 so all is good.

Hope that helps

API design challenge – builder

Now that Windsor 3 is released I can concentrate on some of my other ideas and projects. While working on one of them, called Cartographer, I encountered an interesting API design problem.

 

I have a class (a builder to be precise) that has a task of setting up a central object (an IMapper implementation) in Cartographer (If you’ve ever used Autofac, it is somewhat analogous to ContainerBuilder). What is interesting about it, is I have three goals for that class:

  1. Provide API for high level configuration and extension points that are universal to and intrinsic to any IMapper implementation.
  2. Provide API for low level configuration of the default IMapper implementation that the builder creates, that will meet the following criteria:
    1. Not force user to customize anything, as the default setup should be enough to get started in most cases.
    2. Allow users to easily swap/extend parts of the dependency chain of the default mapper.
    3. Work well and be natural both with and without IoC container .
  3. Be simple and discoverable to the users (and provide good Intellisense experience).

How would you design the API for this class?

 

Oh, and happy new year.

Windsor 3 beta 1 is released (along with other goodies)

The title says it all. If you can’t wait grab the binaries here (Windsor with Castle Core and facilities) and here (just Core). Nuget package will hopefully follow soon.

What’s in it?

This is a major release and there’s quite a lot of new features, as well as some significant changes under the covers. There’s a high level overview of highlights for the release in the wiki, so please have a look there. More detailed changelog, and list of breaking changes is available as part of the package.

Remember it’s a beta release. Documentation and samples are still being updated and some features are not yet implemented or not fully baked. However it is very important that you don’t wait for the final release to upgrade, so that we can find and fix all the issues before final release. I’m not asking you to use it in production, but I’d really appreciate if you’d take the time to branch your apps, try to upgrade, run your unit tests, play with new version, and report any issues you may find. And ask your colleagues, friends and random people on the street to do the same!

And if you find any issues, do report them.

Have fun and happy coding,
I hope you like it

IronRuby, Nu project and Launchy at your service

There’s been some buzz lately about the nu project that uses ruby gems infrastructure to let you quickly and easily grab latest version of common (and not so common) open source libraries without having to go and hunt for them.

All you need to do, is to open a command line, type

nu install foo

and you’ll get the project foo installed on your machine.

If you’re lazy, like me this may seem like too much. If you’re a Launchy user, like me – I have a solution for you.

launcyh

Go to plugins, select runner and add entry for nu as on the screenshot above. For “Program” section type path to your nu.bat file which you’ll find in your Ruby, or Iron Ruby install directory. As arguments type $$ which means “whatever I pass” and you’re done.

Now you can open Launchy, type nu <tab> install project-name and few moments later the selected project is on your hard disk. Simple, hopefully useful.

nuj

dotless

Castle Windsor (incl. Core with DynamicProxy and Dictionary Adapter) v2.5 final is out

Exactly one month after beta 2, I’m happy to announce that Windsor, as well as Castle Core (which now includes DynamicProxy and Dictionary Adapter) 2.5 are officially released.

Single .zip contains the following versions:

  • .NET 3.5 (sp1)
  • .NET 4.0
  • .NET 4.0 Client Profile
  • Silverlight 3
  • Silverlight 4

Changes, changes, changes

For the list of changes see announcement for beta 1, and beta 2 or changes.txt file in the package. Since beta 2 the following changes were made:

  • debugger view support has been extracted to a separate subsystem (IContainerDebuggerExtensionHost) and can be extended by users code via IContainerDebuggerExtension and IComponentDebuggerExtension
  • calling IHandler.TryStart will no longer silently ignore all the exceptions.
  • added CollectionResolver which is a more general version of ArrayResolver and ListResolver and supports in addition ICollection<Foo> and IEnumerable<Foo>
  • fixed issue where dependencies would not be cleaned up when component creation failed
  • fixed issue where startable component would be created twice when property dependency could not be resolved
  • passing arguments to ILazyComponentLoader (see breakingchanges.txt)
  • fixed bug that caused exception when proxied component and it’s proxied property dependency shared interceptor

Samples

For now we have a single sample application (Silverlight 4 app), created by Hadi Eskandari. You’re still welcome to contribute more apps, and hopefully soon we’ll have more of them.

New issue tracker

While not strictly related to the release, we also deployed a new issue tracker, which should be much easier to use.

Downloads

The package is here (Core with DynamicProxy and Dictionary Adapter) and here (Windsor with Logging Facility and Synchronize Facility). Enjoy.

Mapping different types with NHibernate – IUserType

warninglabel_thumb[1]

Recently I had a problem with the application I’ve been working on. One of entity types in my domain had a property of type uint. Not a big deal, until you want to store it in Microsoft SQL Server database which does not support unsigned types. I’ve been scratching my head for a moment and then I found a solution – let’s map it as long in our database. Since long can represent any legal value of uint, we should be all good, right? So let’s do it.

public class ClassWithUintProperty
{
    private Guid Id { get; set; }
    public virtual uint UintProp { get ;set; }
}

<?xml version="1.0"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="NHibernate.Test"
                   namespace="NHibernate.Test">
  <class name="ClassWithUintProperty">
    <id name="Id"/>
    <property name="UIntProp" not-null="true" type="long" />
  </class>
</hibernate-mapping>

 

“Houston, we’ve had a problem”

All good. At least until you try to fetch saved value from the database. When you do, you’re up for an unpleasant surprise:

System.InvalidCastException: Specified cast is not valid.

NHibernate.PropertyAccessException: Invalid Cast (check your mapping for property type mismatches); setter of NHibernate.Test.UIntAsLong

The exception is a result of how NHibernate optimizes property access and quirks of mixing different conversion operators (unboxing and numeric conversion in this case) and are not really interesting. What’s important, is that we approached the problem from the wrong angle.

What we’re dealing with here, is inability of our database engine to deal with datatype in our model, which we were trying to solve by pushing this onto NHibernate without telling it something is ‘”wrong”. While NHibernate is smart, it’s working based on a set of explicit information, so what we need to do, is to be explicit about what we want it to do.

There are two places where we can tell NHibernate about it.

  • IUserType, which will explicitly handle the mapping from uint in our model to long in the DB
  • custom Dialect which will basically lie to NHibernate telling it “yeah, sure this DB supports uints – whole dozens of ‘em!” and do some work under the covers to live up to its promise. (not shown in this post).

 

Enter IUserType

IUserType is an extension point in NHibernate that let’s you plug in to the mapping process and handle it yourself. The interface is quite big, but there’s very little real logic there:

public class UIntAsLong:IUserType
{
        public SqlType[] SqlTypes
        {
            get { return new[] { SqlTypeFactory.Int64 }; }
        }
 
        public Type ReturnedType
        {
            get { return typeof( uint ); }
        }
 
        public bool IsMutable
        {
            get { return false; }
        }
 
        public int GetHashCode( object x )
        {
            if( x == null )
            {
                return 0;
            }
            return x.GetHashCode();
        }
 
        public object NullSafeGet( IDataReader rs, string[] names, object owner )
        {
            object obj = NHibernateUtil.UInt32.NullSafeGet( rs, names0 );
            if( obj == null )
            {
                return null;
            }
            return (uint)obj;
        }
 
        public void NullSafeSet( IDbCommand cmd, object value, int index )
        {
            Debug.Assert( cmd != null);
            if( value == null )
            {
                ((IDataParameter)cmd.Parametersindex).Value = DBNull.Value;
            }
            else
            {
                var uintValue = (uint)value;
                ( (IDataParameter) cmd.Parametersindex ).Value = (long) uintValue;
            }
        }
 
        public object DeepCopy( object value )
        {
            // we can ignore it...
            return value;
        }
 
        public object Replace( object original, object target, object owner )
        {
            // we can ignore it...
            return original;
        }
 
        public object Assemble( object cached, object owner )
        {
            // we can ignore it...
            return cached;
        }
 
        public object Disassemble( object value )
        {
            // we can ignore it...
            return value;
        }
 
        bool IUserType.Equals( object x, object y )
        {
            return object.Equals( x, y );
        }
} 

There are really two parts of the code that are interesting. SqlTypes / ReturnedType properties which tell NHibernate which types to expect on both sides of the mapping, and the NullSafeGet / NullSafeSet methods which perform the actual conversion.

Now we just need to plug our custom user type to the mapping, and it goes like this:

<?xml version="1.0"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="NHibernate.Test"
                   namespace="NHibernate.Test">
  <class name="ClassWithUintProperty">
    <id name="Id"/>
    <property name="UIntProp" not-null="true" type="Foo.Namespace.UIntAsLong, Foo.Assembly" />
  </class>
</hibernate-mapping>

Technorati Tags:

Adjusting NHibernate mapping for tests

As nice as SQLite is for tests it is very simple database, and it does not have all the options ‘big’ databases provide (foreign key enforcement!). I don’t think there’s much you can do about this issue, but there’s more.

SQLite does not support all the mappings you can have. I bumped into this issue when working with mapping similar to described in this post. Basically when you try to create schema from this mapping:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" 
                   namespace="ConsoleApplication1" 
                   assembly="ConsoleApplication1">
  <class name="Invoice">
    <id name="Id">
      <generator class="guid.comb" />
    </id>
    <property name="InvoiceRtfString" type="StringClob">
      <column name ="RtfText" sql-type="nvarchar(MAX)"/>
    </property>
    <property name="ScannedInvoiceJpg" type="BinaryBlob">
      <column name ="JpgData" sql-type="varbinary(max)" />
    </property>
  </class>
</hibernate-mapping>

You’ll get an error:

SQLite error near “MAX”: syntax error

That’s because SQLite does not know how to handle nvarchar(max) or varbinary(max). It has its own types for that – TEXT and BLOB. So you’re either stuck, or have two sets of mappings – one for tests for SQLite, one for production, for SQL Server. But wait, there’s third option!

In the previous post, you may have noticed, that in DbTestsBase Init method I call:

new Remapper().Remap(configuration);

Remapper is my remedy for that problem. It’s a simple class that traverses the mapping looking for incompatibilities and adjusts it on the fly before creating session factory and schema. This lets you have single mapping (be it XML or FluentNHibernate) while still using SQLite for tests.

The class looks like this:

public class Remapper
{
    private IDictionary<string, String> map = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
 
    public Remapper()
    {
        map.Add("varbinary(max)", "BLOB");
        map.Add("nvarchar(max)", "TEXT");
    }
 
    public void Remap(Configuration configuration)
    {
        foreach (var classMapping in configuration.ClassMappings)
        {
            this.Remap(classMapping.Table);
        }
    }
 
    private void Remap(Table table)
    {
 
        if (table.Name.Contains("."))
        {
            // found on http://www.nablasoft.com/alkampfer/index.php/2009/07/24/manage-in-memory-nhibernate-test-with-sqlite-and-database-schema/
            // this is a table with schema
            table.Name = table.Name.Replace(".", "_");
        }
 
        foreach (var column in table.ColumnIterator)
        {
            this.Remap(column);
        }
 
    }
 
    private void Remap(Column column)
    {
        if (string.IsNullOrEmpty(column.SqlType))
        {
            return;
        }
 
        string sqlType;
        if (!this.map.TryGetValue(column.SqlType, out sqlType))
        {
            return;
        }
 
        column.SqlType = sqlType;
    }
}

It is very simple and basic, because I created it for my very specific needs, but with little effort you could extend it to handle more incompatibilities.

Technorati Tags: ,

Framework Tips XIII: Testing Random code

Question

How do you test code that is random. For example say you have a class that allows some action with 60% probability:

public class UsingRandom
{
    private Random generator;
    public double probability = 0.6D;
 
    public bool ShouldAllow()
    {
        return generator.NextDouble() < probability;
    }
}

How do you unit test that?

 

Answer

The answer is staggeringly simple – you fake it. Raise your hand if you knew that methods in the Random class are virtual (I didn’t). Ok, now you can put your hand down, both of you.

virtual_random

With that knowledge, all you have to do is to inject an appropriate fake into the class during your test, and you’re done.

 

Technorati Tags: ,