Skip to content

Repository files navigation

XFEExtension.NetCore.AutoConfig

NuGetNuGet DownloadsLicense: MIT.NET

📖 English | 简体中文

Description

XFEExtension.NetCore.AutoConfig is a .NET library powered by Roslyn incremental source generators. It automatically generates static properties, load/save methods, and persistence logic for any partial class that inherits from XFEProfile, eliminating the need to write boilerplate configuration code.

Getting Started

Installation

dotnet add package XFEExtension.NetCore.AutoConfig

Basic Usage

Annotate fields with [ProfileProperty]. The source generator will create a corresponding static property that automatically saves whenever it is assigned:

// Define a profile class[AutoLoadProfile]partialclassSystemProfile:XFEProfile{[ProfileProperty]stringname=string.Empty;[ProfileProperty]int_age;}// Use the profileclassProgram{staticvoidMain(string[]args){SystemProfile.Name="Test";// Automatically saved on assignmentConsole.WriteLine(SystemProfile.Name);Console.WriteLine(SystemProfile.Age);// Restored from disk on next run}}

Note: The [AutoLoadProfile] attribute instructs the framework to call LoadProfile() inside the static constructor, so the configuration is restored automatically when the program starts.

Automatic saves are coalesced over a 100 ms window by default. A burst of assignments therefore produces one complete file write instead of one write per property. Call SaveProfile() when the current snapshot must be flushed immediately.


Detailed Usage

Automatic Save Performance and Concurrency

Generated properties, ProfileList<T>, and ProfileDictionary<TKey, TValue> are synchronized for concurrent access. Automatic save requests are handled by one writer per profile and coalesced using AutoSaveDelay. Files are committed through a temporary file and atomic replacement, so readers never observe a partially written configuration.

The coalescing window can be customized in the profile constructor:

publicSystemProfile(){AutoSaveDelay=TimeSpan.FromMilliseconds(500);}

Current.LastSaveException exposes the most recent background save failure and is cleared after a successful save. Explicit SaveProfile() calls remain synchronous and surface write failures directly.

Changing the Storage Format

Set DefaultProfileOperationMode inside the instance constructor to switch the storage format. The file extension is updated automatically:

[AutoLoadProfile]partialclassSystemProfile:XFEProfile{[ProfileProperty]stringname=string.Empty;[ProfileProperty]int_age;publicSystemProfile(){DefaultProfileOperationMode=ProfileOperationMode.Xml;// Switch to XML; extension becomes .xml// Available modes: XFEDictionary (default), Json, Xml, Custom}}

Custom Storage Path and File Extension

Use the generated static properties ProfilePath and ProfileExtension to control where the file is stored:

[AutoLoadProfile]partialclassSystemProfile:XFEProfile{[ProfileProperty]stringname=string.Empty;[ProfileProperty]int_age;publicSystemProfile(){ProfilePath=$"MyPath/MySubPath/{nameof(SystemProfile)}";// Path without extensionProfileExtension=".ini";// Custom file extension}}

ProfilePath and ProfileExtension are generated static properties and can also be set from outside the class:

SystemProfile.ProfilePath="custom/path/SystemProfile";SystemProfile.ProfileExtension=".cfg";

Using the [ProfilePath] Attribute

[AutoLoadProfile][ProfilePath("MyPath/MySubPath/SystemProfile")]partialclassSystemProfile:XFEProfile{[ProfileProperty]stringname=string.Empty;[ProfileProperty]int_age;}

Custom Load and Save Operations

Set DefaultProfileOperationMode to Custom and provide your own load/save delegates:

[AutoLoadProfile]partialclassSystemProfile:XFEProfile{[ProfileProperty]stringname=string.Empty;[ProfileProperty]int_age;publicSystemProfile(){DefaultProfileOperationMode=ProfileOperationMode.Custom;ProfilePath=$"MyPath/MySubPath/{nameof(SystemProfile)}";ProfileExtension=".ini";LoadOperation=MyCustomLoadProfileOperation;SaveOperation=MyCustomSaveProfileOperation;}// Custom load methodpublicstaticXFEProfile?MyCustomLoadProfileOperation(XFEProfileprofileInstance,stringprofileString,Dictionary<string,Type>propertyInfoDictionary,Dictionary<string,SetValueDelegate>propertySetFuncDictionary){// Implement custom load logic herereturnnull;}// Custom save methodpublicstaticstringMyCustomSaveProfileOperation(XFEProfileprofileInstance,Dictionary<string,Type>propertyInfoDictionary,Dictionary<string,GetValueDelegate>propertyGetFuncDictionary){// Implement custom save logic herereturnstring.Empty;}}

Storing Collections with ProfileList and ProfileDictionary

ProfileList<T> and ProfileDictionary<TKey, TValue> request a coalesced automatic save whenever the collection is modified (add, remove, clear, index assignment, etc.). Their public operations and enumeration snapshots are safe to use concurrently:

[AutoLoadProfile]partialclassSystemProfile:XFEProfile{[ProfileProperty][ProfilePropertyAddGet("Current.nameList.CurrentProfile = Current")][ProfilePropertyAddGet("return Current.nameList")]ProfileList<string>nameList=[];[ProfileProperty][ProfilePropertyAddGet("Current.nameIdDictionary.CurrentProfile = Current")][ProfilePropertyAddGet("return Current.nameIdDictionary")]ProfileDictionary<string,long>nameIdDictionary=[];}classProgram{staticvoidMain(string[]args){SystemProfile.NameList.Add("Alice");// Auto-saved on addSystemProfile.NameList.AddRange(["Bob","Carol"]);// Batch addSystemProfile.NameList.Remove("Bob");// Auto-saved on removeSystemProfile.NameIdDictionary.Add("Alice",100L);// Dictionary works the same way}}

Injecting Code into get/set Accessors

Use [ProfilePropertyAddGet] and [ProfilePropertyAddSet] to insert code snippets directly into the generated property accessors:

[AutoLoadProfile]partialclassSystemProfile:XFEProfile{[ProfileProperty][ProfilePropertyAddGet(@"Console.WriteLine(""Getting Name"")")][ProfilePropertyAddGet("return Current.name")][ProfilePropertyAddSet(@"Console.WriteLine(""Setting Name"")")][ProfilePropertyAddSet("Current.name = value")]stringname=string.Empty;[ProfileProperty][ProfilePropertyAddGet(@"Console.WriteLine(""Getting Age"")")][ProfilePropertyAddGet("return Current._age")][ProfilePropertyAddSet(@"Console.WriteLine(""Setting Age"")")][ProfilePropertyAddSet("Current._age = value")]int_age;}

Note: When using [ProfilePropertyAddGet], you must handle the full return statement yourself in the last get snippet.

Partial Method Hooks

The generator creates static partial void GetXxxProperty() and static partial void SetXxxProperty(ref T value) for each property. Implement them in your own partial class to intercept reads and writes:

[AutoLoadProfile]partialclassSystemProfile:XFEProfile{[ProfileProperty]stringname=string.Empty;[ProfileProperty]int_age;staticpartialvoidGetNameProperty(){Console.WriteLine("Name was read");}staticpartialvoidSetNameProperty(refstringvalue){Console.WriteLine($"Name changing: {Name} -> {value}");}staticpartialvoidGetAgeProperty(){Console.WriteLine("Age was read");}staticpartialvoidSetAgeProperty(refintvalue){value=1999;// Modify the value before it is storedConsole.WriteLine($"Age forced to 1999");}}

Default Field Values

Assign values directly at the field declaration site:

[AutoLoadProfile]partialclassSystemProfile:XFEProfile{[ProfileProperty]stringname="John Wick";[ProfileProperty]int_age=59;}

XML Documentation Comments

XML doc comments placed on a field are automatically propagated to the generated static property:

[AutoLoadProfile]partialclassSystemProfile:XFEProfile{/// <summary>/// The user's name. This comment is copied to the generated Name property./// </summary>[ProfileProperty]stringname=string.Empty;[ProfileProperty]int_age;}

Manual Load / Save / Delete / Export / Import

The following static methods are generated for every profile class:

SystemProfile.LoadProfile();// Load from fileSystemProfile.SaveProfile();// Save to fileSystemProfile.DeleteProfile();// Delete the config filestringexported=SystemProfile.ExportProfile();// Export config as a stringSystemProfile.ImportProfile(exported);// Import config from a string

API Reference

Attributes

AttributeTargetDescription
[ProfileProperty]FieldMarks the field for code generation. Optionally specify a property name: [ProfileProperty("CustomName")]
[ProfilePropertyAddGet(code)]FieldAppends a code line to the generated get accessor. Supports multiple attributes.
[ProfilePropertyAddSet(code)]FieldAppends a code line to the generated set accessor. Supports multiple attributes.
[AutoLoadProfile]ClassCalls LoadProfile() automatically in the static constructor.
[ProfilePath(path)]ClassSets the storage path for the config file.

Storage Modes (ProfileOperationMode)

ValueExtensionDescription
XFEDictionary (default).xpfXFE dictionary format
Json.jsonJSON serialization
Xml.xmlXML serialization
CustomcustomUser-provided load/save delegates

Auto-Generated Static Members

For every partial class that inherits XFEProfile and uses [ProfileProperty], the source generator produces:

MemberKindDescription
Currentstatic TThe singleton profile instance
ProfilePathstatic stringStorage path (without extension)
ProfileExtensionstatic stringFile extension (auto-detected when empty)
LoadProfile()static voidLoads config from file
SaveProfile()static voidImmediately saves config to file and waits for completion
DeleteProfile()static voidDeletes the config file
ExportProfile()static stringExports config as a string
ImportProfile(string)static voidImports config from a string
XxxProperty (per field)static TAuto-generated static property; saves on set
InstanceXxx (per field)T (instance)Corresponding instance property
GetXxxProperty()static partial voidInvoked when the property is read
SetXxxProperty(ref T)static partial voidInvoked when the property is written

XFEProfile Base Class Members

MemberKindDescription
DefaultProfileOperationModeProfileOperationModeLoad/save mode
LoadOperationProfileLoadOperationCustom load delegate
SaveOperationProfileSaveOperationCustom save delegate
ProfilesDefaultPathstatic stringDefault root directory for all profile files
AutoSaveDelayTimeSpanCoalescing window for automatic saves (100 ms by default)
LastSaveExceptionException?Most recent background save failure

License

This project is licensed under the MIT License.

About

自动实现配置文件的存储

Resources

Stars

5 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages