Andrew Matthews

Dynamic Strongly-Typed Configuration in C#

I thought it was worth describing this configuration solution, since it was so neat, and easy, and had all of the benefits of text based configuration and strongly typed inline configuration.

    <add key="P2PConfigSettings" value="ChatClient.Configuration.TechChatConfig, ChatClient.Configuration, Version="/>

This simple app setting is the fully qualified type name of the TechChatConfig class on the bottom right of the diagram above. Which will be a default chat configuration with whatever tech chat configuration added. That’s all the prerequisites for loading configuration. Not all I need to do to load the configuration is this:

private static IChatClientConfig GetConfigObject()
    string configType = ConfigurationManager.AppSettings["P2PConfigSettings"];
    Type t = Type.GetType(configType);
    return Activator.CreateInstance(t) as IChatClientConfig;

Get whatever type I specified as a string from the configuration file, get the type specified by that string create and instance and return it. Simple. That configuration could be then stored as a singleton or whatever you need to do.

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public partial class Window1 : IPeerChat
    private IChatClientConfig configuration;

In my case I just stored it in the window object I was using it for – my chat client only has one window! Now I can just use it, whenever I do any comms.

private NetPeerTcpBinding CreateBindingForMesh()
    NetPeerTcpBinding binding = new NetPeerTcpBinding();
    binding.Resolver.Mode = config.PeerResolverMode;
    binding.Security.Transport.CredentialType = config.CredentialType;
    binding.MaxReceivedMessageSize = config.MaxReceivedMessageSize;
    return binding;

So you see that the process is very simple. With the addition of an AddIn model we could use a file system monitor to watch the configuration file, detect changes and reload the configuration object singleton using the mechanism described above. That fulfils most of the requirements that we have for type safety, performance, dynamism, intelligence, and object orientation. Very few configuration scenarios that fall outside of the bounds of this solution should be solved using local configuration settings anyway – in those cases you really ought to be looking at an administration console and database.