https://github.com/slaks/confoxide
Fast, DRY, strongly-typed configuration system for C# projects
https://github.com/slaks/confoxide
c-sharp json options-dialog settings
Last synced: 11 months ago
JSON representation
Fast, DRY, strongly-typed configuration system for C# projects
- Host: GitHub
- URL: https://github.com/slaks/confoxide
- Owner: SLaks
- Created: 2014-01-01T18:39:53.000Z (over 12 years ago)
- Default Branch: master
- Last Pushed: 2017-07-17T15:33:01.000Z (almost 9 years ago)
- Last Synced: 2025-08-01T09:17:10.500Z (11 months ago)
- Topics: c-sharp, json, options-dialog, settings
- Language: C#
- Size: 4.01 MB
- Stars: 11
- Watchers: 2
- Forks: 2
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# ConfOxide
ConfOxide is a library for writing settings classes. You can define your classes using simple C# auto-implemented properties, and ConfOxide will let you easily clone them, compare them, reset them, or save them to (and load them from) JSON files.
Install ConfOxide from [NuGet](https://www.nuget.org/packages/ConfOxide/).
# Example
First, create a settings class:
```CSharp
sealed class ConnectionSettings : SettingsBase {
[DefaultValue(2)]
public int RetryCount { get; set; }
[DefaultValue("00:00:30")]
public TimeSpan RetryDelay { get; set; }
}
sealed class MyAppSettings : SettingsBase {
public IList Endpoints { get; private set; }
[DefaultValue("2013-12-11")]
public DateTime TimelineStart { get; set; }
public int? MaxAge { get; set; }
}
```
Note that concrete settings classes must be `sealed`. To create an inheritable settings class, you must add a type parameter; see below.
## Usage
To create a new settings type, just write `new MyAppSettings()`. All collection & settings properties will be initialized to new instances, and all properties will be set to their default values. All settings methods are implemented as extension methods in the `ConfOxide.SettingsExtensions` class (for performance reasons); to call these methods, you will need to add `using ConfOxide`.
## Working with JSON documents
- To read a settings file from JSON, call `settings.ReadJson(json)` and pass a Json.NET `JObject` instance with the data to read.
- To update a JSON object from an existing settings instance, call `settings.UpdateJson(json)` and pass the `JObject` to update. The existing property order, as well as any extra properties, will be preserved.
- To create a new JSON object from an existing settings instance, call `settings.ToJson()`.
## Working with JSON files
ConfOxide also includes helper methods to read and write JSON files from disk. Call `settings.ReadJsonFile(filename)` to read an existing JSON file, if it exists. Call `settings.WriteJsonFile(filename)` to create or update a JSON file from the settings object
## Working with Settings instances
- Call `settings.IsEquivalentTo(otherSettings)` to check whether two settings instances hold the same values. This is a deep comparison that will recursively compare collections and nested settings objects by value.
- Call `settings.AssignFrom(sourceSettings)` to deeply assign the values from one settings instance to another.
- Call `settings.CreateCopy()` to create a deep clone of a settings instance. (this is shorthand for `new YourSettingsClass().AssignFrom(settings)`
These methods are particularly useful when creating cancellable Options dialogs. You can call `settings.CreateCopy()` to bind your options dialog to a deep copy of the settings class, call `copy.IsEquivalentTo(copy)` to check whether there are any changes to apply, and call `settings.AssignFrom(copy)` to apply changes when clicking OK.
## Supported types
ConfOxide supports properties of all basic .Net types, including primitive numeric types, `decimal`, `string`, `DateTime`, `DateTimeOffset`, and `TimeSpan`, all enums, as well as nullable types thereof.
Properties containing other `SettingsBase` classes are also supported, as long as there are no circular dependencies.
ConfOxide also supports collection properties of other `SettingsBase` classes or of supported scalar types. You can use any collection class that is writable, variable-sized, and has a default constructor. If you make a property of type `IList`, ConfOxide will create a `List` to assign to the property. Note that arrays are not supported.
# FAQ
- **Q: What does the name mean?**
A: ConfOxide is a portmanteau of “Configuration” and “Carbon Dioxide” (dry ice). The point of this library is to allow [DRY](http://en.wikipedia.org/wiki/Don't_repeat_yourself "Don't Repeat Yourself") configuration classes.
- **Q: Wouldn't writing the serialization & cloning code by hand be faster?**
A: Nope!
ConfOxide uses advanced techniques to compile strongly-typed accessor code at runtime, avoiding all boxing (except when saving to JSON; Json.NET does not expose any way to save value types without boxing).
At the cost of a slight longer initialization time (to build the accessor code for each type using reflection), ConfOxide should be exactly as fast as code you write by hand.
- **Q: Why are all of the utility methods defined as extension methods?**
A: To avoid extra casting. Had those methods been defined in the base `SettingsBase` class, it would have been impossible to access properties from derived classes without casting `this` (this is a limitation in C#'s type system). By using extension methods with the [CRTP](http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern "Curiously recurring template pattern"), I can access the properties of `T` directly using pre-created delegates.
- **Q: Do I need to write a constructor?**
A: Nope! The base `SettingsBase` constructor will automatically initialize all nested collection & settings properties, and apply all declared default values.
- **Q: How can I declare a default value for a collection property?**
A: .Net doesn't provide any decent way to do that. Instead, override the `ResetCustom()` and populate the collection in code. This method will be called after each instance is constructed, as well as after `ResetValues()` is called.
- **Q: Can I create a base classes with common properties and have multiple concrete settings classes inherit it?**
A: Sure. However, in order to make the type-safe accessor logic work, the intermediary class also needs to implement the [CRTP](http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern "Curiously recurring template pattern"):
```CSharp
abstract class VersionedSettingsBase : SettingsBase where T : VersionedSettingsBase {
[DefaultValue(1)]
public int Version { get; set; }
}
sealed class MyAppSettings : VersionedSettingsBase {
// ...
}
```
- **Q: What about XML?**
A: If enough people are interested in serializing to XML in addition to JSON, I'll add support for that.
# License
[MIT](http://opensource.org/licenses/MIT)