A powerful, type-safe preference management library for .NET MAUI that extends the built-in Preferences API with encryption, caching, observables, and strongly-typed configuration. Designed for simplicity, performance, and scalability.
License
—
Deps
24
Install Size
—
Vulns
✓ 0
Published
Nov 9, 2025
$ dotnet add package Shaunebu.MAUI.PreferenceManager
Shaunebu.MAUI.PreferenceManager is a powerful, type-safe wrapper around MAUI's built-in Preferences system that provides enhanced functionality, security, and superior developer experience for managing application settings in .NET MAUI applications.
| Feature | MAUI Preferences | Shaunebu.PreferenceManager | Benefit |
|---|---|---|---|
| Type Safety 🔒 | ❌ Separate methods per type | ✅ Single generic methods | Fewer runtime errors |
| Complex Objects 🏢 | ❌ Manual serialization | ✅ Automatic JSON serialization | Store any object easily |
| Caching ⚡ | ❌ No caching | ✅ Memory cache with expiration | 10x faster reads |
| Observables 🔄 | ❌ No reactive support | ✅ Rx.NET integration | Real-time UI updates |
| Error Handling 🚨 | ❌ Generic exceptions | ✅ Specific exception types | Better debugging |
| Encryption 🔐 | ❌ No encryption | ✅ Basic encryption support | Better security |
| Dependency Injection 💉 | ❌ Static class | ✅ DI-ready services | Better architecture |
| Strongly-Typed Wrapper 🎯 | ❌ Not available | ✅ TypedPreferenceManager<T> | Type-safe settings |
| Migration Support 🚚 | ❌ Manual migration | ✅ Built-in migration methods | Easier app updates |
| Configuration ⚙️ | ✅ With sharedName | ✅ Flexible options config | More control |
dotnet add package Shaunebu.MAUI.PreferenceManager
// In MauiProgram.cs
builder.Services.AddPreferenceManager(options =>
{
options.SharedName = "MyApp";
options.EnableEncryption = true;
options.EnableCaching = true;
options.CacheDuration = TimeSpan.FromMinutes(10);
});
public class MainViewModel
{
private readonly IPreferenceManager _preferences;
public MainViewModel(IPreferenceManager preferences)
{
_preferences = preferences;
}
// Store preferences
_preferences.Set("Username", "JohnDoe");
_preferences.Set("UserAge", 25);
_preferences.Set("IsPremium", true);
// Retrieve preferences
var username = _preferences.Get<string>("Username");
var age = _preferences.Get<int>("UserAge");
var isPremium = _preferences.Get<bool>("IsPremium");
}
// No more type-specific methods!
_preferences.Set("Temperature", 23.5); // double
_preferences.Set("LastLogin", DateTime.Now); // DateTime
_preferences.Set("UserSettings", userObject); // Complex object
public class UserSettings
{
public string Theme { get; set; }
public bool Notifications { get; set; }
public int RefreshRate { get; set; }
}
var settings = new UserSettings {
Theme = "Dark",
Notifications = true
};
// Automatic JSON serialization/deserialization
_preferences.Set("AppSettings", settings);
var loaded = _preferences.Get<UserSettings>("AppSettings");
// Subscribe to preference changes
_preferences.PreferenceChanged.Subscribe(args =>
{
if (args.Key == "Theme")
{
// Update UI in real-time!
ApplyTheme(args.NewValue?.ToString());
}
});
// Trigger changes anywhere
_preferences.Set("Theme", "Dark"); // All subscribers notified!
// Encrypt sensitive data
_preferences.SetSecure("AuthToken", "super-secret-token");
_preferences.SetSecure("UserCredentials", loginData);
// Decrypt automatically
var token = _preferences.GetSecure<string>("AuthToken");
public class AppConfig
{
public string Language { get; set; } = "en";
public bool DarkMode { get; set; } = false;
public int CacheSize { get; set; } = 100;
}
// Create typed manager
var configManager = new TypedPreferenceManager<AppConfig>(_preferences);
// Load all settings
var config = configManager.Load();
// Modify and save
config.DarkMode = true;
configManager.Save(config);
// Migrate from old key to new key
_preferences.MigratePreference("old_theme_key", "new_theme_key");
// Remove old key automatically
_preferences.MigratePreference("deprecated_setting", "new_setting", removeOld: true);
builder.Services.AddPreferenceManager(options =>
{
options.EnableCaching = true;
options.CacheDuration = TimeSpan.FromMinutes(5); // Cache for 5 minutes
});
try
{
var data = _preferences.Get<ComplexObject>("MyData");
}
catch (SerializationException ex)
{
// Handle serialization errors
Console.WriteLine($"Failed to deserialize: {ex.Message}");
}
catch (PreferenceManagerException ex)
{
// Handle other preference errors
Console.WriteLine($"Preference error: {ex.Message}");
}
// Multiple preferences at once
var preferences = new Dictionary<string, object>
{
["Theme"] = "Dark",
["Notifications"] = true,
["FontSize"] = 14
};
foreach (var pref in preferences)
{
_preferences.Set(pref.Key, pref.Value);
}
Enable Caching: Reduces disk I/O for frequently accessed preferences
Use Appropriate Cache Duration: Balance between memory and freshness
Batch Related Settings: Use TypedPreferenceManager<T> for groups of settings
Disable Cache for Rarely Accessed Data: Set EnableCaching = false for large, rarely used objects
// Use descriptive keys
_preferences.Set("UserProfile_Theme", "Dark");
// Group related settings
_preferences.Set("Appearance_Theme", "Dark");
_preferences.Set("Appearance_FontSize", 14);
// Use secure storage for sensitive data
_preferences.SetSecure("Auth_Token", jwtToken);
// Avoid generic keys
_preferences.Set("key1", data); // ❌ What is key1?
// Don't store large objects in preferences
_preferences.Set("LargeImage", hugeByteArray); // ❌ Use file storage instead
| Method | Description |
|---|---|
T Get<T>(string key, T defaultValue) | Retrieve preference |
void Set<T>(string key, T value) | Store preference |
bool Remove(string key) | Remove preference |
bool ContainsKey(string key) | Check if key exists |
void Clear() | Remove all preferences |
T GetSecure<T>(string key, T defaultValue) | Get encrypted preference |
void SetSecure<T>(string key, T value) | Set encrypted preference |
IObservable<PreferenceChangedEventArgs> PreferenceChanged | Observable for changes |
| Method | Description |
|---|---|
T Load() | Load all settings as typed object |
void Save(T settings) | Save all settings from typed object |
TValue Get<TValue>(Expression<Func<T, TValue>>) | Get specific property |
void Set<TValue>(Expression<Func<T, TValue>>, TValue) | Set specific property |
public class ThemeService
{
private readonly IPreferenceManager _preferences;
public ThemeService(IPreferenceManager preferences)
{
_preferences = preferences;
// React to theme changes
_preferences.PreferenceChanged
.Where(args => args.Key == "CurrentTheme")
.Subscribe(args => ApplyTheme(args.NewValue?.ToString()));
}
public string CurrentTheme
{
get => _preferences.Get("CurrentTheme", "Light");
set => _preferences.Set("CurrentTheme", value);
}
}
public class UserSettingsService
{
private readonly TypedPreferenceManager<UserPreferences> _preferences;
public UserSettingsService(IPreferenceManager preferenceManager)
{
_preferences = new TypedPreferenceManager<UserPreferences>(preferenceManager);
}
public UserPreferences GetSettings() => _preferences.Load();
public void SaveSettings(UserPreferences settings) => _preferences.Save(settings);
public void UpdateTheme(string theme)
{
var settings = _preferences.Load();
settings.Theme = theme;
_preferences.Save(settings);
}
}