Binding nodes to models

Binding is the process of initializing a model (an instance of almost arbitrary type) with data from a settings tree obtained from a configuration source:

node {A: 1, B: 2} --> new CustomModel { A = 1, B = 2}

The resulting model is queried by the application code with a configuration provider to access settings.

Binders

Binding is implemented by a set of binders, each of which knows how to convert a settings node to an object of a specific type.

Binders are composable: if there's a registered binder for Dictionary<T1, T2>, string and int, then it's possible to bind to Dictionary<string, int>. This is heavily used for collections.

Overview

A typical binding process starts with a class binder and proceeds downward by matching fields and properties with scoped node subtrees by names and invoking appropriate binders:

Node:

{
  Timeout1: "1 seconds",
  Timeout2: "2 seconds"
  Logging:
  {
    Enabled: "true",
    Levels: ["Info", "Warn"]
  }
}
Model:

class AppSettings 
{
    public TimeSpan Timeout1 { get; }
    public TimeSpan Timeout2 { get; }
    public LoggingSettings Logging { get; }
    
    class LoggingSettings
    {
        public bool Enabled { get; }
        public LogLevel[] Levels { get; }
    }
}
Binding process:

Node --> AppSettings via ClassStructBinder
  Node["timeout1"] --> Timeout1 via PrimitiveBinder
  Node["timeout2"] --> Timeout2 via PrimitiveBinder
  Node["logging"] --> Logging via ClassStructBinder
    Node["logging"]["enabled"] --> Enabled via PrimitiveBinder
    Node["logging"]["levels"] --> Levels via ArrayBinder
      Node["logging"]["levels"][0] --> Levels[0] by EnumBinder
      Node["logging"]["levels"][1] --> Levels[1] by EnumBinder

See all binders descriptions to learn more about this process.

Error handling

Binding fails if there's at least one error on any level. Errors may arise from incorrect value formats for primitives, missing values for required fields and properties, mismatches of settings node types or missing binders for requested types.

In case of failure, a complete list of all errors is presented in resulting exception.

Last updated