A generic persistence provider library that supports multiple storage backends for .NET applications. This library is designed to complement and integrate with ktsu.SerializationProvider and ktsu.FileSystemProvider libraries, providing a clean abstraction layer for data persistence with dependency injection support.
- Multiple Storage Backends: Memory, file system, application data, and temporary storage
- Dependency Injection Ready: Designed for use with DI containers
- Async/Await Support: All operations are asynchronous
- Generic Key Support: Use any type as a key (string, Guid, int, etc.)
- Serialization Integration: Works with any ktsu.SerializationProvider implementation
- File System Integration: Leverages ktsu.FileSystemProvider for file operations
- Thread-Safe: Concurrent operations are handled safely
# Install from NuGet
dotnet add package ktsu.PersistenceProviderusing ktsu.PersistenceProvider;
using ktsu.SerializationProvider;
// Create a serialization provider (implementation not shown)
ISerializationProvider serializer = new JsonSerializationProvider(); // or any other implementation
// Create a memory-based persistence provider
IPersistenceProvider<string> provider = new MemoryPersistenceProvider<string>(serializer);
// Store an object
await provider.StoreAsync("user:123", new UserSettings
{
Theme = "Dark",
Language = "en-US"
});
// Retrieve the object
var settings = await provider.RetrieveAsync<UserSettings>("user:123");
// Check if an object exists
bool exists = await provider.ExistsAsync("user:123");
// Remove an object
await provider.RemoveAsync("user:123");using ktsu.PersistenceProvider;
using ktsu.FileSystemProvider;
using ktsu.SerializationProvider;
// Create providers
IFileSystemProvider fileSystem = new FileSystemProvider(); // or any other implementation
ISerializationProvider serializer = new JsonSerializationProvider();
// Create file system-based persistence provider
IPersistenceProvider<string> provider = new FileSystemPersistenceProvider<string>(
fileSystem,
serializer,
@"C:\MyApp\Data");
// Use same interface as memory provider
await provider.StoreAsync("config", new AppConfig { Version = "1.0" });
var config = await provider.RetrieveAsync<AppConfig>("config");using ktsu.PersistenceProvider;
using ktsu.FileSystemProvider;
using ktsu.SerializationProvider;
// Create providers
IFileSystemProvider fileSystem = new FileSystemProvider();
ISerializationProvider serializer = new JsonSerializationProvider();
// Create AppData-based persistence provider (stores in %APPDATA%\MyApp)
IPersistenceProvider<string> provider = new AppDataPersistenceProvider<string>(
fileSystem,
serializer,
"MyApp");
// With optional subdirectory (stores in %APPDATA%\MyApp\Settings)
IPersistenceProvider<string> providerWithSubdir = new AppDataPersistenceProvider<string>(
fileSystem,
serializer,
"MyApp",
"Settings");
// Store application data
await provider.StoreAsync("preferences", new UserPreferences
{
AutoSave = true,
CheckForUpdates = false
});using ktsu.PersistenceProvider;
using ktsu.FileSystemProvider;
using ktsu.SerializationProvider;
// Create temporary storage provider
IPersistenceProvider<Guid> provider = new TempPersistenceProvider<Guid>(
fileSystemProvider,
serializationProvider,
"MyApp");
// Store temporary data
Guid sessionId = Guid.NewGuid();
await provider.StoreAsync(sessionId, new SessionData { StartTime = DateTime.UtcNow });
// Clean up on dispose
using var tempProvider = provider as TempPersistenceProvider<Guid>;
tempProvider?.Dispose(cleanupDirectory: true);Register persistence providers in your DI container:
using Microsoft.Extensions.DependencyInjection;
var services = new ServiceCollection();
// Register dependencies
services.AddSingleton<ISerializationProvider, JsonSerializationProvider>();
services.AddSingleton<IFileSystemProvider, FileSystemProvider>();
// Register persistence providers
services.AddSingleton<IPersistenceProvider<string>>(provider =>
new MemoryPersistenceProvider<string>(
provider.GetRequiredService<ISerializationProvider>()));
services.AddSingleton<IPersistenceProvider<Guid>>(provider =>
new FileSystemPersistenceProvider<Guid>(
provider.GetRequiredService<IFileSystemProvider>(),
provider.GetRequiredService<ISerializationProvider>(),
@"C:\MyApp\Data"));
// Register AppData provider
services.AddSingleton<IPersistenceProvider<string>>(provider =>
new AppDataPersistenceProvider<string>(
provider.GetRequiredService<IFileSystemProvider>(),
provider.GetRequiredService<ISerializationProvider>(),
"MyApp"));
// Use in your services
services.AddTransient<IUserService, UserService>();- Storage: In-memory dictionary
- Persistence: No (data lost on application exit)
- Use Case: Caching, temporary data, testing
- Thread Safety: Yes (ConcurrentDictionary)
- Storage: File system as JSON files
- Persistence: Yes (survives application restart)
- Use Case: Configuration files, user data, application state
- Thread Safety: Yes (atomic file operations)
- Storage: Application data directory (%APPDATA%\ApplicationName on Windows)
- Persistence: Yes (survives application restart)
- Use Case: User-specific application data, settings, preferences
- Thread Safety: Yes (atomic file operations)
- Storage: System temporary directory
- Persistence: Limited (may be cleaned up by system)
- Use Case: Temporary files, cache, session data
- Thread Safety: Yes (atomic file operations)
public interface IPersistenceProvider<TKey> where TKey : notnull
{
string ProviderName { get; }
bool IsPersistent { get; }
Task StoreAsync<T>(TKey key, T obj, CancellationToken cancellationToken = default);
Task<T?> RetrieveAsync<T>(TKey key, CancellationToken cancellationToken = default);
Task<T> RetrieveOrCreateAsync<T>(TKey key, CancellationToken cancellationToken = default) where T : new();
Task<bool> ExistsAsync(TKey key, CancellationToken cancellationToken = default);
Task<bool> RemoveAsync(TKey key, CancellationToken cancellationToken = default);
Task<IEnumerable<TKey>> GetAllKeysAsync(CancellationToken cancellationToken = default);
Task ClearAsync(CancellationToken cancellationToken = default);
}All providers throw PersistenceProviderException for operation failures:
try
{
await provider.StoreAsync("key", data);
}
catch (PersistenceProviderException ex)
{
// Handle persistence-specific errors
Console.WriteLine($"Storage failed: {ex.Message}");
}This library is designed to work with:
- ktsu.SerializationProvider: For object serialization/deserialization
- ktsu.FileSystemProvider: For file system operations with testing support
- Any DI Container: Microsoft.Extensions.DependencyInjection, Autofac, etc.
dotnet build PersistenceProvider.slndotnet test PersistenceProvider.slnThis library follows the same patterns and conventions as other ktsu.dev libraries. Please ensure:
- All public APIs are documented with XML comments
- Code follows established patterns from SerializationProvider and FileSystemProvider
- Tests are included for new functionality
- Changes are backward compatible
MIT License - see LICENSE file for details.