Add TryGet overloads for string and ISpanParsable types in managed configuration

This commit is contained in:
Thorsten Sommer 2025-10-19 11:36:07 +02:00
parent 9925cbff40
commit 97f8f6d2a2
Signed by: tsommer
GPG Key ID: 371BBA77A02C0108
2 changed files with 199 additions and 8 deletions

View File

@ -91,7 +91,7 @@ public static partial class ManagedConfiguration
LuaTable settings, LuaTable settings,
bool dryRun, bool dryRun,
ISpanParsable<TValue>? _ = null) ISpanParsable<TValue>? _ = null)
where TValue : ISpanParsable<TValue> where TValue : struct, ISpanParsable<TValue>
{ {
// //
// Handle configured ISpanParsable values // Handle configured ISpanParsable values

View File

@ -12,7 +12,7 @@ public static partial class ManagedConfiguration
/// <summary> /// <summary>
/// Attempts to retrieve the configuration metadata for a given configuration selection and /// Attempts to retrieve the configuration metadata for a given configuration selection and
/// property expression. /// property expression (enum-based).
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// When no configuration metadata is found, it returns a NoConfig instance with the default /// When no configuration metadata is found, it returns a NoConfig instance with the default
@ -31,6 +31,7 @@ public static partial class ManagedConfiguration
Expression<Func<Data, TClass>> configSelection, Expression<Func<Data, TClass>> configSelection,
Expression<Func<TClass, TValue>> propertyExpression, Expression<Func<TClass, TValue>> propertyExpression,
out ConfigMeta<TClass, TValue> configMeta) out ConfigMeta<TClass, TValue> configMeta)
where TValue : Enum
{ {
var configPath = Path(configSelection, propertyExpression); var configPath = Path(configSelection, propertyExpression);
if (METADATA.TryGetValue(configPath, out var value) && value is ConfigMeta<TClass, TValue> meta) if (METADATA.TryGetValue(configPath, out var value) && value is ConfigMeta<TClass, TValue> meta)
@ -47,6 +48,84 @@ public static partial class ManagedConfiguration
return false; return false;
} }
/// <summary>
/// Attempts to retrieve the configuration metadata for a given configuration selection and
/// property expression (string-based).
/// </summary>
/// <remarks>
/// When no configuration metadata is found, it returns a NoConfig instance with the default
/// value set to default(TValue). This allows the caller to handle the absence of configuration
/// gracefully. In such cases, the return value of the method will be false.
/// </remarks>
/// <param name="configSelection">The expression to select the configuration class.</param>
/// <param name="propertyExpression">The expression to select the property within the
/// configuration class.</param>
/// <param name="configMeta">The output parameter that will hold the configuration metadata
/// if found.</param>
/// <typeparam name="TClass">The type of the configuration class.</typeparam>
/// <returns>True if the configuration metadata was found, otherwise false.</returns>
public static bool TryGet<TClass>(
Expression<Func<Data, TClass>> configSelection,
Expression<Func<TClass, string>> propertyExpression,
out ConfigMeta<TClass, string> configMeta)
{
var configPath = Path(configSelection, propertyExpression);
if (METADATA.TryGetValue(configPath, out var value) && value is ConfigMeta<TClass, string> meta)
{
configMeta = meta;
return true;
}
configMeta = new NoConfig<TClass, string>(configSelection, propertyExpression)
{
Default = string.Empty,
};
return false;
}
/// <summary>
/// Attempts to retrieve the configuration metadata for a given configuration selection and
/// property expression (ISpanParsable-based).
/// </summary>
/// <remarks>
/// When no configuration metadata is found, it returns a NoConfig instance with the default
/// value set to default(TValue). This allows the caller to handle the absence of configuration
/// gracefully. In such cases, the return value of the method will be false.
/// </remarks>
/// <param name="configSelection">The expression to select the configuration class.</param>
/// <param name="propertyExpression">The expression to select the property within the
/// configuration class.</param>
/// <param name="configMeta">The output parameter that will hold the configuration metadata
/// if found.</param>
/// <param name="_">An optional parameter to help with method overload resolution.</param>
/// <typeparam name="TClass">The type of the configuration class.</typeparam>
/// <typeparam name="TValue">The type of the property within the configuration class.</typeparam>
/// <returns>True if the configuration metadata was found, otherwise false.</returns>
// ReSharper disable MethodOverloadWithOptionalParameter
public static bool TryGet<TClass, TValue>(
Expression<Func<Data, TClass>> configSelection,
Expression<Func<TClass, TValue>> propertyExpression,
out ConfigMeta<TClass, TValue> configMeta,
ISpanParsable<TValue>? _ = null)
where TValue : struct, ISpanParsable<TValue>
{
var configPath = Path(configSelection, propertyExpression);
if (METADATA.TryGetValue(configPath, out var value) && value is ConfigMeta<TClass, TValue> meta)
{
configMeta = meta;
return true;
}
configMeta = new NoConfig<TClass, TValue>(configSelection, propertyExpression)
{
Default = default!,
};
return false;
}
// ReSharper restore MethodOverloadWithOptionalParameter
/// <summary> /// <summary>
/// Attempts to retrieve the configuration metadata for a list-based setting. /// Attempts to retrieve the configuration metadata for a list-based setting.
/// </summary> /// </summary>
@ -163,19 +242,131 @@ public static partial class ManagedConfiguration
/// <typeparam name="TClass">The type of the configuration class.</typeparam> /// <typeparam name="TClass">The type of the configuration class.</typeparam>
/// <typeparam name="TValue">The type of the property within the configuration class.</typeparam> /// <typeparam name="TValue">The type of the property within the configuration class.</typeparam>
/// <returns>True if the configuration setting is left over and was reset, otherwise false.</returns> /// <returns>True if the configuration setting is left over and was reset, otherwise false.</returns>
public static bool IsConfigurationLeftOver<TClass, TValue>(Expression<Func<Data, TClass>> configSelection, Expression<Func<TClass, TValue>> propertyExpression, IEnumerable<IAvailablePlugin> availablePlugins) public static bool IsConfigurationLeftOver<TClass, TValue>(
Expression<Func<Data, TClass>> configSelection,
Expression<Func<TClass, TValue>> propertyExpression,
IEnumerable<IAvailablePlugin> availablePlugins)
where TValue : Enum
{ {
if (!TryGet(configSelection, propertyExpression, out var configMeta)) if (!TryGet(configSelection, propertyExpression, out var configMeta))
return false; return false;
if(configMeta.MangedByConfigPluginId == Guid.Empty || !configMeta.IsLocked) if (configMeta.MangedByConfigPluginId == Guid.Empty || !configMeta.IsLocked)
return false;
var plugin = availablePlugins.FirstOrDefault(x => x.Id == configMeta.MangedByConfigPluginId);
if (plugin is null)
{
configMeta.ResetManagedState();
return true;
}
return false;
}
public static bool IsConfigurationLeftOver<TClass>(
Expression<Func<Data, TClass>> configSelection,
Expression<Func<TClass, string>> propertyExpression,
IEnumerable<IAvailablePlugin> availablePlugins)
{
if (!TryGet(configSelection, propertyExpression, out var configMeta))
return false;
if (configMeta.MangedByConfigPluginId == Guid.Empty || !configMeta.IsLocked)
return false;
var plugin = availablePlugins.FirstOrDefault(x => x.Id == configMeta.MangedByConfigPluginId);
if (plugin is null)
{
configMeta.ResetManagedState();
return true;
}
return false;
}
// ReSharper disable MethodOverloadWithOptionalParameter
public static bool IsConfigurationLeftOver<TClass, TValue>(
Expression<Func<Data, TClass>> configSelection,
Expression<Func<TClass, TValue>> propertyExpression,
IEnumerable<IAvailablePlugin> availablePlugins,
ISpanParsable<TValue>? _ = null)
where TValue : struct, ISpanParsable<TValue>
{
if (!TryGet(configSelection, propertyExpression, out var configMeta))
return false;
if (configMeta.MangedByConfigPluginId == Guid.Empty || !configMeta.IsLocked)
return false;
var plugin = availablePlugins.FirstOrDefault(x => x.Id == configMeta.MangedByConfigPluginId);
if (plugin is null)
{
configMeta.ResetManagedState();
return true;
}
return false;
}
// ReSharper restore MethodOverloadWithOptionalParameter
public static bool IsConfigurationLeftOver<TClass, TValue>(
Expression<Func<Data, TClass>> configSelection,
Expression<Func<TClass, IList<TValue>>> propertyExpression,
IEnumerable<IAvailablePlugin> availablePlugins)
{
if (!TryGet(configSelection, propertyExpression, out var configMeta))
return false;
if (configMeta.MangedByConfigPluginId == Guid.Empty || !configMeta.IsLocked)
return false;
var plugin = availablePlugins.FirstOrDefault(x => x.Id == configMeta.MangedByConfigPluginId);
if (plugin is null)
{
configMeta.ResetManagedState();
return true;
}
return false;
}
public static bool IsConfigurationLeftOver<TClass, TValue>(
Expression<Func<Data, TClass>> configSelection,
Expression<Func<TClass, ISet<TValue>>> propertyExpression,
IEnumerable<IAvailablePlugin> availablePlugins)
{
if (!TryGet(configSelection, propertyExpression, out var configMeta))
return false;
if (configMeta.MangedByConfigPluginId == Guid.Empty || !configMeta.IsLocked)
return false;
var plugin = availablePlugins.FirstOrDefault(x => x.Id == configMeta.MangedByConfigPluginId);
if (plugin is null)
{
configMeta.ResetManagedState();
return true;
}
return false;
}
public static bool IsConfigurationLeftOver<TClass>(
Expression<Func<Data, TClass>> configSelection,
Expression<Func<TClass, IDictionary<string, string>>> propertyExpression,
IEnumerable<IAvailablePlugin> availablePlugins)
{
if (!TryGet(configSelection, propertyExpression, out var configMeta))
return false;
if (configMeta.MangedByConfigPluginId == Guid.Empty || !configMeta.IsLocked)
return false; return false;
// Check if the configuration plugin ID is valid against the available plugin IDs:
var plugin = availablePlugins.FirstOrDefault(x => x.Id == configMeta.MangedByConfigPluginId); var plugin = availablePlugins.FirstOrDefault(x => x.Id == configMeta.MangedByConfigPluginId);
if (plugin is null) if (plugin is null)
{ {
// Remove the locked state:
configMeta.ResetManagedState(); configMeta.ResetManagedState();
return true; return true;
} }