Announcing ConfigR 1.0

Β· 814 words Β· 4 minutes to read

Recently we released version 1.0 of ConfigR - a popular .NET configuration library, that lets you configure your application via C# scripts (CSX).

This is also the last release requiring full .NET 4.5/Mono - the next version of ConfigR is going to be a netstandard.

Here’s a overview of the features that are there in 1.0!

What’s new πŸ”—

Here is the overview of the new features.

New NuGet packages πŸ”—

ConfigR is no longer coupled to C# scripting - instead it’s merely a configuration abstraction, and it’s just the abstraction code that is contained in the main ConfigR package.

This means that while scripting is the primary (or rather - at the moment - the only) way to use ConfigR, the ConfigR abstraction could be implemented against any configuration provider, allowing you to seamlessly merge multiple sources into a single configuration model (along with the scripting one).

To use ConfigR as a CSX/scripting configuration source, install the new ConfigR.Roslyn.CSharp package.

New Syntax πŸ”—

ConfigR 1.0 introduces a new, simplified syntax of building up your configuration. Instead of calling Add method from your configuration CSX script, you can just use a global dynamic dictionary.

Additionally, changes are done to how you consume ConfigR in the host application, and that’s related to the fact that ConfigR can potentially have multiple configuration sources (as explained in the previous section).

Let’s have a look at some examples. First, the old syntax - no longer in use in ConfigR 1.0 - for some context.

// old CSX syntax
Add("Count", 123);
Add("Link", new Uri("https://github.com/config-r/config-r"));

// app
void Main(string[] args)
{ 
    var count = Config.Global.Get<int>("Count");  // it's a System.Int32!
    var link = Config.Global.Get<Uri>("Link");    // it's a System.Uri!
}

In ConfigR 1.0.0 you can assign the values to a global object “Config” directly:

//new CSX syntax
Config.Link = new Uri("https://github.com/config-r/config-r");
Config.Count = 123;

Now, there are a few ways to retrieve the values. Loading values must be set up upfront with the correct loader (at the moment it would always be Roslyn scripting) and is an async operation.

The most elegant approach to load configuration would be to use a POCO. For example:

class MyConfig
{
    public int Count {get; set;}    
    public Uri Link {get; set;} 
}

// app
void Main(string[] args)
{ 
    // set up ConfigR to use Roslyn CSX scripting and load the config into a POCO
    var config = new Config().UseRoslynCSharpLoader().Load<MyConfig>().GetAwaiter().GetResult();

    var count = config.Count;  // it's a System.Int32!
    var link = config.Link;    // it's a System.Uri!
}

Another approach is to use dynamic loading:

// app
void Main(string[] args)
{ 
    // set up ConfigR to use Roslyn CSX scripting and load the config into dynamic object
    var config = new Config().UseRoslynCSharpLoader().LoadDynamic().GetAwaiter().GetResult();

    var count = config.Count;  // it's a dynamic with System.Int32 under the hood
    var link = config.Link;    // it's a dynamic with System.Uri under the hood
}

Finally it’s also possible to load into an IDictionary<string, object>:

// app
void Main(string[] args)
{ 
    // set up ConfigR to use Roslyn CSX scripting and load the config into a dictionary
    var config = new Config().UseRoslynCSharpLoader().LoadDictionary().GetAwaiter().GetResult();

    var count = config["Count"];  // it's an object with System.Int32 under the hood
    var link = config["Link"];    // it's an object with System.Uri under the hood
}

Implicit reference back to the main project πŸ”—

The configuration script now has an implicit back reference to the main application, meaning that from within the script you can easily access all of the public types defined in your application.

In the past, in order to reference host application types you had to manually use #r directive.

#r "ConfigRDemo.exe"

using ConfigRDemo;

// DataTarget enum comes from the host app 
Add("DataTarget", DataTarget.Production);

Similar code in ConfigR 1.0 is less verbose:

using ConfigRDemo;

Config.DataTarget = DataTarget.Production;

Less dependencies and Mono compatibility πŸ”—

ConfigR is now leaner, as it doesn’t depend on scriptcs anymore - instead it’s completely standalone (the main ConfigR abstraction) or only built directly on Roslyn (the CSX COnfigR loader).

This also means it’s also Mono compatible right now, and paves an easy way to a .NET Core port in the next release. Oh, and the dreaded JSON.NET dependency was dropped too.

Support for loading remote scripts πŸ”—

#load directives now supports HTTP based references. Thus you can distribute and delegate your configuration to remote services.

The example is shown below.

// foo.csx hosted remotely
Config.Link = new Uri("https://github.com/config-r/config-r");

// CSX embedded into the app
#load "http://localhost/foo.csx"
Config.Count = 123;

Other bug fixes and small improvements πŸ”—

A bunch of other bug fixes an improvements were done. For example, ConfigR supports in-memory assemblies, meaning you can now use it to configure applications which only exist in memory and are never flushed into a physical assembly on disk.

Oh and there is a new logo πŸ™‚

If you wanna help building ConfigR (next step - netstandard!) - stop by Github!

Finally, huge thanks to Adam who has been the mastermind behind all this.

About


Hi! I'm Filip W., a cloud architect from ZΓΌrich πŸ‡¨πŸ‡­. I like Toronto Maple Leafs πŸ‡¨πŸ‡¦, Rancid and quantum computing. Oh, and I love the Lowlands 🏴󠁧󠁒󠁳󠁣󠁴󠁿.

You can find me on Github, on Mastodon and on Bluesky.

My Introduction to Quantum Computing with Q# and QDK book
Microsoft MVP