RecordCommander 1.0.0
dotnet add package RecordCommander --version 1.0.0
NuGet\Install-Package RecordCommander -Version 1.0.0
<PackageReference Include="RecordCommander" Version="1.0.0" />
<PackageVersion Include="RecordCommander" Version="1.0.0" />
<PackageReference Include="RecordCommander" />
paket add RecordCommander --version 1.0.0
#r "nuget: RecordCommander, 1.0.0"
#:package RecordCommander@1.0.0
#addin nuget:?package=RecordCommander&version=1.0.0
#tool nuget:?package=RecordCommander&version=1.0.0
RecordCommander
RecordCommander is a C# library that enables you to create, update, and manage records using a command-line–inspired interface. With a focus on simplicity and flexibility, RecordCommander allows you to register your data types, define unique keys and property mappings, and use both positional and named arguments to seed data or integrate with import/export systems.
Features
- Command-Based Record Management: Create or update records using single-line commands (e.g.,
add language nl Dutch). - Flexible Configuration: Register classes by specifying unique keys, positional property order, and named property assignments.
- Data Seeding & Import/Export: Ideal for seeding data, providing sample data for documentation, or integrating with external systems.
- JSON–Like Parsing: Supports complex property values (including arrays) with JSON–like syntax.
- No External Dependencies: Uses only the default Microsoft libraries.
- Aliases & Short Names: Apply
[Alias]on classes or properties to use shorter command tokens. - Custom Commands & Method Calls: Extend the registry with
RegisterCommandor call object methods via--Method:arg=value. - Usage Generation: Generate commands, usage examples and prompts for custom commands.
- Custom Converters & Enum/Flags Support: Register converters for your types and work with enums or flag combinations.
Getting Started
Installation
Simply clone the repository and include the source code in your project. Since RecordCommander relies solely on standard .NET libraries, no additional NuGet packages are required.
Or install the library via NuGet Package Manager Console:
Install-Package RecordCommander
Configuration
Before running commands, register your record types with the library. For example, suppose you have the following domain classes:
public class MyData
{
public List<Language> Languages { get; set; } = new List<Language>();
public List<Country> Countries { get; set; } = new List<Country>();
}
public class Language
{
public string Key { get; set; }
public string Name { get; set; }
}
public class Country
{
public string Code { get; set; }
public string Name { get; set; }
public string[] SpokenLanguages { get; set; } = Array.Empty<string>();
}
You would register them as follows:
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using RecordCommander;
// Register the Language record.
RecordCommandRegistry.Register<MyData, Language>(
name: "language",
collectionAccessor: ctx => ctx.Languages,
uniqueKeySelector: x => x.Key,
positionalPropertySelectors: new Expression<Func<Language, object>>[] { x => x.Name }
);
// Register the Country record.
RecordCommandRegistry.Register<MyData, Country>(
name: "country",
collectionAccessor: ctx => ctx.Countries,
uniqueKeySelector: x => x.Code,
positionalPropertySelectors: new Expression<Func<Country, object>>[] { x => x.Name, x => x.SpokenLanguages }
);
The AliasAttribute can be used on classes and properties to provide alternative names for the command and properties. For example:
[Alias("lang")]
public class Language
{
public string Key { get; set; }
[Alias("n")]
public string Name { get; set; }
}
Running Commands
After registration, you can execute commands that create or update records in your data context. For example:
// Create a context instance.
var context = new MyData();
// Run commands to seed or update data.
RecordCommandRegistry.Run(context, "add language nl Dutch");
RecordCommandRegistry.Run(context, "add language fr French");
RecordCommandRegistry.Run(context, "add country be Belgium");
// Update an existing record using named arguments:
RecordCommandRegistry.Run(context, "add country be --SpokenLanguages=['nl','fr']");
// Or using the aliases:
RecordCommandRegistry.Run(context, "add lang de --n=German");
Example Output
After executing the commands above, you might see output like:
Languages:
Key: nl, Name: Dutch
Key: fr, Name: French
Countries:
Code: be, Name: Belgium, SpokenLanguages: nl, fr
How It Works
Registration:
You register each record type with a command name, a lambda to access the target collection from your context, and expressions that define the unique key and positional properties.Command Parsing:
TheRunmethod tokenizes the input command. It supports quoted strings, simple escape sequences, and recognizes tokens prefixed with--as named property assignments. Likewise theRunManymethod supports multiple commands in a single string, separated by newlines, ignoring empty lines and lines starting with#.Record Updating/Creation:
The library searches for an existing record using the unique key. If found, it updates the record’s properties; otherwise, it creates a new record and adds it to the collection.Type Conversion:
Values are converted to the target property types using built-in conversion mechanisms. Array values can be provided in a JSON–like syntax for easy parsing.
Features
Named Arguments
You can use named arguments to update properties of an existing record. For example:
RecordCommandRegistry.Run(context, "add country be --SpokenLanguages=['nl','fr']");
Multiple Commands
You can run multiple commands in a single string, separated by newlines. For example:
RecordCommandRegistry.RunMany(context, @"
add language nl Dutch
add language fr French
add country be Belgium
add country be --SpokenLanguages=['nl','fr']
");
Comments
You can add comments to your command strings by starting a line with #. For example:
RecordCommandRegistry.RunMany(context, @"
add language nl Dutch
add language fr French
# Add Belgium with Dutch and French as spoken languages
add country be --SpokenLanguages=['nl','fr']
");
Alias Attribute
You can use the AliasAttribute to provide alternative names for the command and properties. For example:
[Alias("lang")]
public class Language
{
public string Key { get; set; }
[Alias("n")]
public string Name { get; set; }
}
Custom Commands
You can create custom commands by calling the RegisterCommand method. For example:
RecordCommandRegistry<MyData>.RegisterCommand("clear", (MyData ctx) => ctx.Languages.Clear());
RecordCommandRegistry.Run(context, "clear");
Custom Commands with optional arguments
You can create custom commands with optional arguments by calling the RegisterCommand method. For example:
RecordCommandRegistry<MyData>.RegisterCommand("clear", (MyData ctx, string argument, int optionalArg = 10) => ctx.Languages.Clear());
RecordCommandRegistry.Run(context, "clear arg1");
RecordCommandRegistry.Run(context, "clear arg1 20");
Custom Conversions
You can register custom converters for the types. For example:
RecordCommandRegistry<TestContext>.RegisterCustomConverter((ctx, code) => ctx.Countries.Find(c => c.Code == code));
Generating Commands
You can generate commands from existing records. For example:
var lang = new Language { Key = "en", Name = "English Language" };
var cmd = RecordCommandRegistry<TestContext>.GenerateCommand(lang);
Assert.Equal("add language en \"English Language\"", cmd);
Method Mapping
You can call methods on your objects using the --Property:Argument=Value syntax. For example:
// Assuming Language has a method SetLabel(string culture, string label)
RecordCommandRegistry.Run(context, "add language en English --SetLabel:de=Englisch");
This will find or create a language with key "en", set its Name to "English", and then call the SetLabel method with arguments "de" and "Englisch".
Command Generation Options
When generating commands from existing objects, you can control the output format using CommandGenerationOptions:
// Generate with aliases instead of full property names
var options = new CommandGenerationOptions(preferAliases: true);
var cmd = RecordCommandRegistry<MyData>.GenerateCommand(record, options);
// Generate with named arguments instead of positional properties
var options = new CommandGenerationOptions(usePositionalProperties: false);
var cmd = RecordCommandRegistry<MyData>.GenerateCommand(record, options);
// Include default values in the generated command
var options = new CommandGenerationOptions(ignoreDefaultValues: false);
var cmd = RecordCommandRegistry<MyData>.GenerateCommand(record, options);
Generating Usage Examples
RecordCommander can generate usage examples for your registered commands:
// Get a basic usage example
string example = RecordCommandRegistry<MyData>.GetUsageExample<Country>();
// Output: "add country <Code> <Name> <SpokenLanguages>"
// Get a detailed usage example with parameter descriptions
string detailed = RecordCommandRegistry<MyData>.GetDetailedUsageExample<Country>();
// Output includes parameter types and descriptions
This is particularly useful for documentation or CLI help text.
Custom Command Prompts
GetCustomCommandPrompt can generate usage text for a custom command and even include parameter descriptions:
string prompt = RecordCommandRegistry<TestContext>.GetCustomCommandPrompt("log4");
// log4 <log> <x> <y> <z> <ts> <g>
string detailed = RecordCommandRegistry<TestContext>.GetCustomCommandPrompt("log4", true);
/*
log4 <log> <x> <y> <z> <ts> <g>
# log : string (quoted if contains spaces) - Message to log
# x : date (format yyyy-MM-dd)
# y : date (format yyyy-MM-dd)
# z : number
# ts : timespan
# g : guid
*/
This is helpful when building CLI help text for custom operations.
Enum and Flags Support
RecordCommander handles both regular enums and flags enums:
// Using a regular enum
RecordCommandRegistry.Run(context, "add book 978-1234567890 \"My Book\" \"Jane Doe\" --Status=Borrowed");
// Using a flags enum (combine multiple values with commas)
RecordCommandRegistry.Run(context, "add book 978-1234567890 \"My Book\" \"Jane Doe\" --Flags=Fiction,Mystery,Romance");
Default Value Handling
RecordCommander respects the DefaultValueAttribute on properties:
public class SampleRecord
{
public string Id { get; set; }
[DefaultValue(-1)]
public int Age { get; set; } = -1;
[DefaultValue(true)]
public bool IsActive { get; set; } = true;
}
When generating commands, properties with default values can be omitted:
var record = new SampleRecord { Id = "123", Name = "Alice" };
var cmd = RecordCommandRegistry<MyData>.GenerateCommand(record);
// Age and IsActive won't appear in the command if they have default values
Use Cases
AI
Once you have a simple set of commands, you can use AI models to let you generate the data for you, for example giving the following propmt to GPT-4o:
add country BE "Belgium" --SpokenLanguages=['nl','fr']
add country DE "Germany" --SpokenLanguages=["de"]
add country FR "France" --SpokenLanguages=["fr"]
can you extend the list with all the EU countries in the same format as above
It will then generate the following output:
add country AT "Austria" --SpokenLanguages=["de"]
add country BE "Belgium" --SpokenLanguages=['nl','fr']
add country BG "Bulgaria" --SpokenLanguages=["bg"]
add country HR "Croatia" --SpokenLanguages=["hr"]
add country CY "Cyprus" --SpokenLanguages=["el"]
add country CZ "Czech Republic" --SpokenLanguages=["cs"]
add country DK "Denmark" --SpokenLanguages=["da"]
add country EE "Estonia" --SpokenLanguages=["et"]
add country FI "Finland" --SpokenLanguages=["fi", "sv"]
add country FR "France" --SpokenLanguages=["fr"]
add country DE "Germany" --SpokenLanguages=["de"]
add country EL "Greece" --SpokenLanguages=["el"]
add country HU "Hungary" --SpokenLanguages=["hu"]
add country IE "Ireland" --SpokenLanguages=["en", "ga"]
add country IT "Italy" --SpokenLanguages=["it"]
add country LV "Latvia" --SpokenLanguages=["lv"]
add country LT "Lithuania" --SpokenLanguages=["lt"]
add country LU "Luxembourg" --SpokenLanguages=["lb", "fr", "de"]
add country MT "Malta" --SpokenLanguages=["mt", "en"]
add country NL "Netherlands" --SpokenLanguages=["nl"]
add country PL "Poland" --SpokenLanguages=["pl"]
add country PT "Portugal" --SpokenLanguages=["pt"]
add country RO "Romania" --SpokenLanguages=["ro"]
add country SK "Slovakia" --SpokenLanguages=["sk"]
add country SI "Slovenia" --SpokenLanguages=["sl"]
add country ES "Spain" --SpokenLanguages=["es"]
add country SE "Sweden" --SpokenLanguages=["sv"]
Dev Data
You can use this library to seed data for your development environment.
Bug Reproduction
You can use this library to reproduce bugs in your application by creating the same data that caused the bug.
Documentation
You can use this library to generate sample data for your documentation. So that the user reading your documentation can copy and paste the commands to seed the data.
Generating commands
You can use this library to generate commands from existing records. Check the following test:
[Fact]
public void Generation_UsingSpaces()
{
var lang = new Language { Key = "en", Name = "English Language" };
var cmd = RecordCommandRegistry<TestContext>.GenerateCommand(lang);
Assert.Equal("add language en \"English Language\"", cmd);
}
This could be used for exporting data from your application.
Limitations (at the moment)
- No Validation:
The library does not perform any validation on the input data. You should validate the data before using it in your application. - Performance:
The library is not optimized for performance. It is designed to be simple and easy to use.
Contributing
Contributions are welcome! If you have suggestions or improvements, please open an issue or submit a pull request.
License
This project is licensed under the MIT License.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- System.Text.Json (>= 10.0.0)
-
net10.0
- No dependencies.
-
net8.0
- No dependencies.
-
net9.0
- No dependencies.
NuGet packages (1)
Showing the top 1 NuGet packages that depend on RecordCommander:
| Package | Downloads |
|---|---|
|
Vidyano
Vidyano is a full featured development platform with the flexibility for creating small to enterprise scale web applications. |
GitHub repositories
This package is not used by any popular GitHub repositories.
