{"id":37056938,"url":"https://github.com/devrexlabs/fig","last_synced_at":"2026-01-14T06:26:37.079Z","repository":{"id":143391580,"uuid":"205725520","full_name":"DevrexLabs/Fig","owner":"DevrexLabs","description":"Libary to help you read application configuration data from different sources","archived":false,"fork":false,"pushed_at":"2023-12-08T13:47:27.000Z","size":162,"stargazers_count":5,"open_issues_count":2,"forks_count":7,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-11-20T14:14:14.143Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DevrexLabs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2019-09-01T19:55:17.000Z","updated_at":"2024-11-26T21:01:18.000Z","dependencies_parsed_at":"2023-11-12T16:30:11.863Z","dependency_job_id":"4d9160b1-b671-4f51-bd85-f45d73ad641b","html_url":"https://github.com/DevrexLabs/Fig","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/DevrexLabs/Fig","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DevrexLabs%2FFig","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DevrexLabs%2FFig/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DevrexLabs%2FFig/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DevrexLabs%2FFig/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DevrexLabs","download_url":"https://codeload.github.com/DevrexLabs/Fig/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DevrexLabs%2FFig/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28412211,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T05:26:33.345Z","status":"ssl_error","status_checked_at":"2026-01-14T05:21:57.251Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-14T06:26:36.462Z","updated_at":"2026-01-14T06:26:37.067Z","avatar_url":"https://github.com/DevrexLabs.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"﻿\n[![Build status](https://ci.appveyor.com/api/projects/status/cp39he84h5ar1edk?svg=true)](https://ci.appveyor.com/project/rofr/fig)\n \n# Fig\nA .NET Standard 2.0 library to help you read application configuration settings from multiple sources. Fig is similar to the Microsoft Configuration Extensions used with AspnetCore but adds some additional behavior yet still has fewer dependencies. \n\nThis README is the documentation.\n\n## Breaking changes with version 2.0!\nPlease read the [Release notes](https://github.com/DevrexLabs/Fig/releases/tag/2.0.24) carefully before upgrading from an older version.\n\n## Documentation\nDo you have code like the following sprinkled across your code base?\n\n```c#\n   var setting = ConfigurationManager.AppSettings[\"CoffeeRefillIntervalInMinutes\"];\n   if (setting == null) setting = \"20\";\n   var refillInterval = TimeSpan.FromMinutes(Int32.Parse(setting));\n```\n\nThere is a lot of stuff going on here:\n \n* Using a string literal key\n* Checking for null\n* Setting a default\n* Converting from string to int\n* Converting to TimeSpan\n\nFig wraps these mundane boilerplate tasks into a simple library letting you either retrieve strongly typed settings by name or bind to the properties of a custom class. The example code above is also tightly coupling to a single configuration source, the web.config or app.config file. Fig supports multiple sources such as environment variables, json files, ini files, sql databases.\n\n\n## Setting up the configuration sources\nLoad configuration data from multiple sources\nusing a fluent builder API. If there are duplicate keys the last one encountered takes precedence. Keys are case insensitive.\n\n```c#\n  var settings = new SettingsBuilder()\n    .UseAppSettingsXml()\n    .UseEnvironmentVariables()\n    .Build();\n```\n\nDo this when your application starts up and then keep a reference to the settings object.\n\n## Binding\nNext, define a simpe class with read/write properties to represent your configurable settings. Now call `settings.Bind\u003cT\u003e()` and Fig will create an instance of T and assign properties with matching names.\n\n```csharp\n   public class CoffeeShopSettings\n   {\n      public TimeSpan RefillInterval { get; set; }\n         = TimeSpan.FromMinutes(10);\n\n      public bool EnableEspressoMachine { get; set; }\n   }\n\n   var settings = new SettingsBuilder()\n      .UseAppSettingsXml()\n      .Build();\n   \n   var coffeeShopSettings = settings.Bind\u003cCoffeeShopSettings\u003e();\n\n   //It's also possible to bind to an existing object\n   var shopSettings = new CoffeeShopSettings();\n   settings.Bind(shopSettings);\n```\n\nBy default, the class name will be used as a qualifier before the property name, so the preceding example will bind to\nthe following keys:\n```\n  CoffeeShopSettings.RefillInterval\n  CoffeeShopSettings.EnableEspressoMachine\n```\n\nChange this behavior by passing an alternative path, not including the \".\":\n\n```csharp\n  //CoffeeShop.RefillInterval\n  settings.Bind\u003cCoffeeShopSettings\u003e(path: \"CoffeeShop\");\n  //or just \"RefillInterval\"\n  settings.Bind\u003cCoffeeShopSettings\u003e(path: \"\")\n```\n\n## Binding to multiple objects\nIn a larger project you probably don't want all the settings in the same class.\nOne solution is to create separate classes to hold subsets of the configuration data.\n\n```csharp\nvar settings = new SettingsBuilder()\n   .UseAppSettingsXml()\n   .Build();\n\nvar dbSettings = settings.Bind\u003cDbSettings\u003e();\nvar networkSettings = settings.Bind\u003cNetworkSettings\u003e();\n```\n\nSo the configuration keys might be:\n\n```\nDbSettings.ReadTimeout\nDbSettings.ConnectionString\nNetworkSettings.TcpPort\nNetworkSettings.Retries\n```\n## Binding to arrays\nAppend indicies to your configuration keys to define an array:\n\n```\nServers.0 = 10.0.0.1\nServers.1 = 10.0.0.2\n```\n\nand then bind to a property of type array:\n\n```csharp\n  class MySettings\n  {\n     public string[] Servers { get; set;}\n  }\n```\nArrays in json files will work this way. See the section below on appsettings.json.\n\n## Variable substitution\n\n## Binding Validation\nProperties are either required or optional. To make a property optional, assign it a non-null value before binding.\n\nNote that value types have non-null defaults. So to make them required, declare using `Nullable\u003cT\u003e`\n\nFig will validate by throwing an exception if any property on the target is null after binding.\n\nYou can disable validation by passing `validation: false` to the `Binding()` methods.\n\nSo given the following class:\n\n```csharp\n   public class CoffeeShopSettings\n   {\n      public TimeSpan? RefillInterval { get; set; }\n      public bool? EnableEspressoMachine { get; set; }\n      public string Greeting { get;set; } = \"Coffee time!\";\n   }\n```\n\nthe `RefillInterval` and `EnableEspressoMachine` parameters are required while the `Greeting` property is optional.\n\n\n## Retrieving values by key\n\nFor simple applications with just a few parameters defining a custom class could be considered over-engineering. In this case you can retrieve values directly by key, either as strings or converted to a desired type.\n\n```csharp\n  //Or grab directly by key\n  var key = \"CoffeeRefillInterval\";\n  var refillInterval = settings.Get\u003cTimeSpan\u003e(key);\n\n  // For optional settings, provide a default using either a lambda or a direct value\n  // lambda can be useful to avoid an expensive calculation\n  var refillInterval = settings.Get(key, () =\u003e TimeSpan.FromMinutes(10));\n\n  //Direct default value\n  var pricePerCup = settings.Get(\"PricePerCup\", 24);\n\n```\nCalling `Get()` without a default will throw a KeyNotFoundException if the key is missing. Keys are not case sensitive.\n\n## Configuration sources\n* web.config / app.config\n* appSettings.json\n* ini-files\n* environment variables\n* command line / string array\n* Sql database\n* Bring your own by implementing `ISettingsSource`\n\nSources provide key value pairs `(string,string)`. \nEach source is described below with an example.\n\n## Web.config / App.config\nGiven this xml configuration:\n```xml\n   \u003cappSettings\u003e\n      \u003cadd key=\"CoffeeShopSettings.espressomachineenabled\" value=\"true\"/\u003e\n      \u003cadd key=\"CoffeeShopSettings.CoffeeRefillInterval\" value=\"00:42:00\"/\u003e\n   \u003c/appSettings\u003e\n   \u003cconnectionStrings\u003e\n    \u003cadd name=\"mydb\"\n      connectionString=\"Data Source=.; Initial Catalog=mydb;Integrated Security=true\"\n      providerName=\"System.Data.SqlClient\"/\u003e\n   \u003c/connectionStrings\u003e\n```\nthe default behavior will yield these keys:\n```\nCoffeeShopSettings.espressomachineenabled\nCoffeeShopSettings.CoffeeRefillInterval\nConnectionStrings.mydb.connectionString\nConnectionStrings.mydb.providerName\n```\n\n## appSettings.json\nThis content:\n```json\n{\n  \"EspressoMachineEnabled\" : true,\n  \"CoffeeRefillInterval\" : \"00:42:00\",\n  \"Timeout\" :  42,\n  \"ConnectionStrings\": {\n    \"DefaultConnection\": \"DataSource=app.db\"\n  },\n  \"Servers\" :  [\"10.0.0.1\", \"10.0.0.2\"],\n  \"Logging\": {\n    \"LogLevel\": {\n      \"Default\": \"Warning\"\n    }\n  },\n  \"AllowedHosts\": \"*\"\n}\n```\nwill be flattened to the following keys:\n```\nEspressoMachineEnabled\nCoffeeRefillInterval\nTimeout\nConnectionStrings.DefaultConnection\nServers.0\nServers.1\nLogging.LogLevel.Default\nAllowedHosts\n```\n## Ini files\nThis input:\n```\nkeya=value\nkeya.keyb=value\n[Network]\nip=10.0.0.3\n[Datasource.A]\nname=value\nconnectionstring=value\n```\nyields these keys:\n```\nkeya\nkeya.keyb\nNetwork.ip\nDatasource.A.name\nDatasource.A.connectionstring\n```\n\n## Environment variables\nGiven these environment variables:\n```bash\nexport ENV=TEST\nexport FIG_TIMEOUT=30\nexport FIG_LOGGING_LOGLEVEL_DEFAULT=Warning\nexport MYAPP_COLOR=Red\nexport MYAPP_ENDPOINT=10.0.0.1:3001\n```\n`builder.UseEnvironmentVariables(prefix: \"FIG_\", dropPrefix:true)` yields:\n```\nTIMEOUT\nLOGGING.LOGLEVEL.DEFAULT\n```\n`builder.UseEnvironmentVariables(prefix: \"MYAPP_\", dropPrefix:false)` yields:\n```\nMYAPP.COLOR\nMYAPP.ENDPOINT\n```\n\n`builder.UseEnvironmentVariables()` yields:\n```\nENV\nFIG.TIMEOUT\nFIG.LOGGING.LOGLEVEL.DEFAULT\nMYAPP.COLOR\nMYAPP.ENDPOINT\n```\n\n## Command line\nFig can take key/value pairs passed on the command line. The default prefix is \"--fig:\" and default separator is \"=\"\n```c#\n//Given\nstring[] args = new []{\n   \"--fig:ENV=Test\",\n   \"--fig:Timeout=30\",\n   \"retries=3\"};\n```\n\n`settingsBuilder.UseCommandLine(args)` yields:\n\n```\nENV\nTimeout\n```\n\nand `settingsBuilder.UseCommandLine(args, prefix: \"\")` yields:\n```\nretries\n``` \n\n## Sql database\nVersion 1.9 introduces SqlSettings. Read keys and values from any sql database\nthat has an ADO.NET provider. (implements `IDbConnection`)\n\nFirst, `Install-Package Fig.SqlSettings`, then use one of the `UseSql` extension method\noverloads to setup a connection to your database. \n\n```csharp\n  //pass an IDbConnection with a preconfigured connection string\n  IDbConnection connection = new SqlConnection(\"Data source=.;Integrated Security=true;Database=mydb\");\n  var settings = new SettingsBuilder()\n   .UseSql(connection)\n   .Build();\n```\n\n```csharp\n  //pass a type parameter for the `IDbConnection` implementation class\n  //and a connection string key to pick up from AppSettingsXml / AppSettingsJson\n  var settings = new SettingsBuilder()\n   .UseAppSettingsJson(\"appsettings.json\")\n   .UseSql\u003cSqlConnection\u003e(\"ConnectionStrings.SQLiteConnection\")\n   .Build();\n```\nThe SQL query used is `SELECT key, value FROM FigSettings`. You can pass your own query:\n\n```csharp\n  var settings = new SettingsBuilder()\n   .UseAppSettingsJson(\"appsettings.json\")\n   .UseSql\u003cSqlConnection\u003e(\"ConnectionStrings.SQLiteConnection\", \"SELECT a,b FROM MySettings\")\n   .Build();\n```\n\n# Combining sources\nUse the `SettingsBuilder` to add sources in order of precedence. \nSettings in above layers override settings with the same key in\nlower layers.\n\n```c#\n   var settings = new SettingsBuilder()\n    .UseEnvironmentVariable(\"ENV\")\n    .UseAppSettingsJson(\"appSettings.json\")\n    .UseAppSettingsJson(\"appSettings.${ENV}.json\", required:false)\n    .UseDotEnv()\n    .UseEnvironmentVariables()\n    .UseCommandLine(args)    \n    .Build\u003cSettings\u003e();\n```\nNotice the variable substitution in the second json file. The variable `${ENV}`\nwill be looked up in the settings dictionary built so far.\n\n## Install from nuget\n```bash\n#Everything in a single bundle\nInstall-Package Fig.All\n\n# the core package with support for command line, json, ini and environment variables\nInstall-Package Fig\n\n# web.config and app.config support is in a separate package\nInstall-Package Fig.AppSettingsXml\n\n#AppSettings json support\nInstall-Package Fig.AppSettingsJson\n\n```\n\n## What do I have?\n`Settings.ToString()` is your friend. It will return a plain-text formatted table\nwith keys and values of each layer:\n\n```\n-------------------- Layer 0 ----------------------\n| Network.ip             | 127.0.0.1              |\n| Network.port           | 13001                  |\n-------------------- Layer 1 ----------------------\n| Network.ip             | 10.0.0.1               |\n| Network.port           | 3001                   |\n---------------------------------------------------\n```\n\n\n## Creating custom sources\n1. Create a class that inherits from `SettingsSource` and overrides `GetSettings()` \n2. Create an extension method for the `SettingsBuilder`\n\n```c#\npublic class MySource : SettingsSource\n{\n   protected override IEnumerable\u003c(string, string)\u003e GetSettings()\n   {\n      //todo: your code goes here\n       yield return (\"key\", \"value\");\n   }\n}\n\npublic static class MySettingsBuilderExtensions\n{\n   public static SettingsBuilder UseMySource(this SettingsBuilder builder)\n   {\n      //do what you have to do\n      var mySource = new MySource();\n\n      //call the inherited ToSettingsDictionary() method\n      //which in turn iterates over your GetSettings() implementation\n      var dictionary = mySource.ToSettingsDictionary();\n\n      // Remember to return the builder to support fluent configuration\n      return builder.UseSettingsDictionary(dictionary);\n   }\n}\n``` \n## Contributing\nContributions are welcome! Check out existing issues, or create a new one,\nand then we discuss details in the comments.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevrexlabs%2Ffig","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdevrexlabs%2Ffig","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevrexlabs%2Ffig/lists"}