mirror of
https://github.com/Tyrrrz/CliFx.git
synced 2025-10-25 15:19:17 +00:00
Cleanup
This commit is contained in:
@@ -28,7 +28,11 @@
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="ApplicationMetadata"/>.
|
||||
/// </summary>
|
||||
public ApplicationMetadata(string title, string executableName, string versionText, string? description)
|
||||
public ApplicationMetadata(
|
||||
string title,
|
||||
string executableName,
|
||||
string versionText,
|
||||
string? description)
|
||||
{
|
||||
Title = title;
|
||||
ExecutableName = executableName;
|
||||
|
||||
@@ -28,44 +28,52 @@ namespace CliFx.Domain
|
||||
|
||||
private Type? TryGetEnumerableArgumentUnderlyingType() =>
|
||||
Property != null && Property.PropertyType != typeof(string)
|
||||
? Property.PropertyType.GetEnumerableUnderlyingType()
|
||||
? Property.PropertyType.TryGetEnumerableUnderlyingType()
|
||||
: null;
|
||||
|
||||
private object? ConvertScalar(string? value, Type targetType)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Custom conversion
|
||||
// Custom conversion (always takes highest priority)
|
||||
if (ConverterType != null)
|
||||
return ConverterType.CreateInstance<IArgumentValueConverter>().ConvertFrom(value!);
|
||||
|
||||
// Primitive
|
||||
// No conversion necessary
|
||||
if (targetType == typeof(object) || targetType == typeof(string))
|
||||
return value;
|
||||
|
||||
// Bool conversion (special case)
|
||||
if (targetType == typeof(bool))
|
||||
return string.IsNullOrWhiteSpace(value) || bool.Parse(value);
|
||||
|
||||
// Primitive conversion
|
||||
var primitiveConverter = PrimitiveConverters.GetValueOrDefault(targetType);
|
||||
if (primitiveConverter != null)
|
||||
if (primitiveConverter != null && !string.IsNullOrWhiteSpace(value))
|
||||
return primitiveConverter(value);
|
||||
|
||||
// Enum
|
||||
if (targetType.IsEnum)
|
||||
// Enum conversion
|
||||
if (targetType.IsEnum && !string.IsNullOrWhiteSpace(value))
|
||||
return Enum.Parse(targetType, value, true);
|
||||
|
||||
// Nullable
|
||||
var nullableUnderlyingType = targetType.GetNullableUnderlyingType();
|
||||
// Nullable<T> conversion
|
||||
var nullableUnderlyingType = targetType.TryGetNullableUnderlyingType();
|
||||
if (nullableUnderlyingType != null)
|
||||
return !string.IsNullOrWhiteSpace(value)
|
||||
? ConvertScalar(value, nullableUnderlyingType)
|
||||
: null;
|
||||
|
||||
// String-constructible
|
||||
// String-constructible conversion
|
||||
var stringConstructor = targetType.GetConstructor(new[] {typeof(string)});
|
||||
if (stringConstructor != null)
|
||||
return stringConstructor.Invoke(new object[] {value!});
|
||||
|
||||
// String-parseable (with format provider)
|
||||
// String-parseable conversion (with format provider)
|
||||
var parseMethodWithFormatProvider = targetType.TryGetStaticParseMethod(true);
|
||||
if (parseMethodWithFormatProvider != null)
|
||||
return parseMethodWithFormatProvider.Invoke(null, new object[] {value!, FormatProvider});
|
||||
|
||||
// String-parseable (without format provider)
|
||||
// String-parseable conversion (without format provider)
|
||||
var parseMethod = targetType.TryGetStaticParseMethod();
|
||||
if (parseMethod != null)
|
||||
return parseMethod.Invoke(null, new object[] {value!});
|
||||
@@ -78,7 +86,10 @@ namespace CliFx.Domain
|
||||
throw CliFxException.CannotConvertToType(this, value, targetType);
|
||||
}
|
||||
|
||||
private object ConvertNonScalar(IReadOnlyList<string> values, Type targetEnumerableType, Type targetElementType)
|
||||
private object ConvertNonScalar(
|
||||
IReadOnlyList<string> values,
|
||||
Type targetEnumerableType,
|
||||
Type targetElementType)
|
||||
{
|
||||
var array = values
|
||||
.Select(v => ConvertScalar(v, targetElementType))
|
||||
@@ -133,7 +144,7 @@ namespace CliFx.Domain
|
||||
return Array.Empty<string>();
|
||||
|
||||
var underlyingType =
|
||||
Property.PropertyType.GetNullableUnderlyingType() ??
|
||||
Property.PropertyType.TryGetNullableUnderlyingType() ??
|
||||
Property.PropertyType;
|
||||
|
||||
// Enum
|
||||
@@ -148,12 +159,9 @@ namespace CliFx.Domain
|
||||
{
|
||||
private static readonly IFormatProvider FormatProvider = CultureInfo.InvariantCulture;
|
||||
|
||||
private static readonly IReadOnlyDictionary<Type, Func<string?, object?>> PrimitiveConverters =
|
||||
new Dictionary<Type, Func<string?, object?>>
|
||||
private static readonly IReadOnlyDictionary<Type, Func<string, object?>> PrimitiveConverters =
|
||||
new Dictionary<Type, Func<string, object?>>
|
||||
{
|
||||
[typeof(object)] = v => v,
|
||||
[typeof(string)] = v => v,
|
||||
[typeof(bool)] = v => string.IsNullOrWhiteSpace(v) || bool.Parse(v),
|
||||
[typeof(char)] = v => v.Single(),
|
||||
[typeof(sbyte)] = v => sbyte.Parse(v, FormatProvider),
|
||||
[typeof(byte)] = v => byte.Parse(v, FormatProvider),
|
||||
|
||||
@@ -385,7 +385,7 @@ namespace CliFx.Domain
|
||||
// Enumerable
|
||||
if (!(defaultValue is string) && defaultValue is IEnumerable defaultValues)
|
||||
{
|
||||
var elementType = defaultValues.GetType().GetEnumerableUnderlyingType() ?? typeof(object);
|
||||
var elementType = defaultValues.GetType().TryGetEnumerableUnderlyingType() ?? typeof(object);
|
||||
|
||||
// If the ToString() method is not overriden, the default value can't be formatted nicely
|
||||
if (!elementType.IsToStringOverriden())
|
||||
|
||||
@@ -14,9 +14,9 @@ namespace CliFx.Internal.Extensions
|
||||
|
||||
public static bool Implements(this Type type, Type interfaceType) => type.GetInterfaces().Contains(interfaceType);
|
||||
|
||||
public static Type? GetNullableUnderlyingType(this Type type) => Nullable.GetUnderlyingType(type);
|
||||
public static Type? TryGetNullableUnderlyingType(this Type type) => Nullable.GetUnderlyingType(type);
|
||||
|
||||
public static Type? GetEnumerableUnderlyingType(this Type type)
|
||||
public static Type? TryGetEnumerableUnderlyingType(this Type type)
|
||||
{
|
||||
if (type.IsPrimitive)
|
||||
return null;
|
||||
@@ -29,7 +29,7 @@ namespace CliFx.Internal.Extensions
|
||||
|
||||
return type
|
||||
.GetInterfaces()
|
||||
.Select(GetEnumerableUnderlyingType)
|
||||
.Select(TryGetEnumerableUnderlyingType)
|
||||
.Where(t => t != null)
|
||||
.OrderByDescending(t => t != typeof(object)) // prioritize more specific types
|
||||
.FirstOrDefault();
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace System.Collections.Generic
|
||||
}
|
||||
|
||||
public static TValue GetValueOrDefault<TKey, TValue>(this IReadOnlyDictionary<TKey, TValue> dic, TKey key) =>
|
||||
dic.TryGetValue(key, out var result) ? result! : default!;
|
||||
dic.TryGetValue(key!, out var result) ? result! : default!;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user