[WIP] Refactor default converters
This commit is contained in:
parent
82594cff34
commit
2daf5b6c1e
@ -11,11 +11,19 @@ namespace Connected
|
|||||||
|
|
||||||
public BoolConverter()
|
public BoolConverter()
|
||||||
{
|
{
|
||||||
SetFunc = OnSet;
|
|
||||||
GetFunc = OnGet;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private T OnGet(bool? value)
|
protected override bool? ConvertValue(T? value)
|
||||||
|
{
|
||||||
|
return OnSet(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override T? ConvertValueBack(bool? value)
|
||||||
|
{
|
||||||
|
return OnGet(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private T OnGet(bool? value)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -31,12 +39,12 @@ namespace Connected
|
|||||||
return (T)(object)(value == true ? 1 : (value == false ? (int?)0 : null));
|
return (T)(object)(value == true ? 1 : (value == false ? (int?)0 : null));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
UpdateGetError($"Conversion to type {typeof(T)} not implemented");
|
TriggerError($"Conversion to type {typeof(T)} not implemented");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
UpdateGetError("Conversion error: " + e.Message);
|
TriggerError("Conversion error: " + e.Message);
|
||||||
return default(T);
|
return default(T);
|
||||||
}
|
}
|
||||||
return default(T);
|
return default(T);
|
||||||
@ -69,13 +77,13 @@ namespace Connected
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
UpdateSetError("Unable to convert to bool? from type " + typeof(T).Name);
|
TriggerError("Unable to convert to bool? from type " + typeof(T).Name);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (FormatException e)
|
catch (FormatException e)
|
||||||
{
|
{
|
||||||
UpdateSetError("Conversion error: " + e.Message);
|
TriggerError("Conversion error: " + e.Message);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,88 +1,111 @@
|
|||||||
using System;
|
using System.Globalization;
|
||||||
using System.Globalization;
|
|
||||||
|
|
||||||
namespace Connected
|
namespace Connected;
|
||||||
|
|
||||||
|
public class Converter<TSourceType, TDestinationType>
|
||||||
{
|
{
|
||||||
public class Converter<T, U>
|
public event EventHandler<string?>? ErrorOccured;
|
||||||
{
|
|
||||||
public Func<T, U> SetFunc { get; set; }
|
|
||||||
public Func<U, T> GetFunc { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The culture info being used for decimal points, date and time format, etc.
|
|
||||||
/// </summary>
|
|
||||||
public CultureInfo Culture { get; set; } = Converters.DefaultCulture;
|
|
||||||
|
|
||||||
public Action<string> OnError { get; set; }
|
|
||||||
public bool SetError { get; set; }
|
|
||||||
public bool GetError { get; set; }
|
|
||||||
public string SetErrorMessage { get; set; }
|
|
||||||
public string GetErrorMessage { get; set; }
|
|
||||||
|
|
||||||
public U Set(T value)
|
|
||||||
{
|
|
||||||
SetError = false;
|
|
||||||
SetErrorMessage = null;
|
|
||||||
if (SetFunc == null)
|
|
||||||
return default(U);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return SetFunc(value);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
SetError = true;
|
|
||||||
SetErrorMessage = $"Conversion from {typeof(T).Name} to {typeof(U).Name} failed: {e.Message}";
|
|
||||||
}
|
|
||||||
return default(U);
|
|
||||||
}
|
|
||||||
|
|
||||||
public T Get(U value)
|
|
||||||
{
|
|
||||||
GetError = false;
|
|
||||||
GetErrorMessage = null;
|
|
||||||
if (GetFunc == null)
|
|
||||||
return default(T);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return GetFunc(value);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
GetError = true;
|
|
||||||
GetErrorMessage = $"Conversion from {typeof(U).Name} to {typeof(T).Name} failed: {e.Message}";
|
|
||||||
}
|
|
||||||
return default(T);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void UpdateSetError(string msg)
|
|
||||||
{
|
|
||||||
SetError = true;
|
|
||||||
SetErrorMessage = msg;
|
|
||||||
OnError?.Invoke(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void UpdateGetError(string msg)
|
|
||||||
{
|
|
||||||
GetError = true;
|
|
||||||
GetErrorMessage = msg;
|
|
||||||
OnError?.Invoke(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Converter from T to string
|
/// The culture info being used for decimal points, date and time format, etc.
|
||||||
///
|
|
||||||
/// Set converts to string
|
|
||||||
/// Get converts from string
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Converter<T> : Converter<T, string>
|
public CultureInfo Culture { get; set; } = Converters.DefaultCulture;
|
||||||
{
|
|
||||||
|
|
||||||
/// <summary>
|
public TDestinationType? Convert(TSourceType value)
|
||||||
/// Custom Format to be applied on bidirectional way.
|
{
|
||||||
/// </summary>
|
try
|
||||||
public string Format { get; set; } = null;
|
{
|
||||||
|
return ConvertValue(value);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
TriggerError($"Conversion from {typeof(TSourceType).Name} to {typeof(TDestinationType).Name} failed: {e.Message}", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual TDestinationType? ConvertValue(TSourceType? value)
|
||||||
|
{
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TSourceType? ConvertBack(TDestinationType value)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return ConvertValueBack(value);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
TriggerError($"Conversion from {typeof(TDestinationType).Name} to {typeof(TSourceType).Name} failed: {e.Message}", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual TSourceType? ConvertValueBack(TDestinationType? value)
|
||||||
|
{
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void TriggerError(string? msg, Exception? e = null)
|
||||||
|
{
|
||||||
|
ErrorOccured?.Invoke(this, msg);
|
||||||
|
|
||||||
|
OnErrorOccured(msg, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void OnErrorOccured(string? msg, Exception? e)
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts values using the supplied lambda functions.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TSourceType">The source type</typeparam>
|
||||||
|
/// <typeparam name="TDestinationType">The destination type</typeparam>
|
||||||
|
public class LambdaConverter<TSourceType, TDestinationType> :Converter<TSourceType, TDestinationType>
|
||||||
|
{
|
||||||
|
private readonly Func<TSourceType, TDestinationType?>? _convertFunction;
|
||||||
|
private readonly Func<TDestinationType, TSourceType?>? _convertBackFunction;
|
||||||
|
|
||||||
|
public LambdaConverter(Func<TSourceType, TDestinationType?>? convertFunction = null, Func<TDestinationType, TSourceType?>? convertBackFunction = null)
|
||||||
|
{
|
||||||
|
_convertFunction = convertFunction;
|
||||||
|
_convertBackFunction = convertBackFunction;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override TDestinationType? ConvertValue(TSourceType? value)
|
||||||
|
{
|
||||||
|
if (_convertFunction is null)
|
||||||
|
return base.ConvertValue(value);
|
||||||
|
|
||||||
|
return _convertFunction.Invoke(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override TSourceType? ConvertValueBack(TDestinationType? value)
|
||||||
|
{
|
||||||
|
if (_convertFunction is null)
|
||||||
|
return base.ConvertValueBack(value);
|
||||||
|
|
||||||
|
return _convertBackFunction.Invoke(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converter from T to string
|
||||||
|
///
|
||||||
|
/// Set converts to string
|
||||||
|
/// Get converts from string
|
||||||
|
/// </summary>
|
||||||
|
public class ToStringConverter<T> : Converter<T, string>
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Custom Format to be applied on bidirectional way.
|
||||||
|
/// </summary>
|
||||||
|
public string? Format { get; set; } = null;
|
||||||
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System.Globalization;
|
using Connected.Extensions;
|
||||||
|
using System.Globalization;
|
||||||
|
|
||||||
namespace Connected
|
namespace Connected
|
||||||
{
|
{
|
||||||
@ -7,9 +8,8 @@ namespace Connected
|
|||||||
public static CultureInfo DefaultCulture = CultureInfo.CurrentUICulture;
|
public static CultureInfo DefaultCulture = CultureInfo.CurrentUICulture;
|
||||||
|
|
||||||
#region --> Date converters
|
#region --> Date converters
|
||||||
public static Converter<DateTime> IsoDate
|
public static LambdaConverter<DateTime, string> IsoDate
|
||||||
=> new()
|
=> new(SetIsoDate, GetIsoDate);
|
||||||
{ SetFunc = SetIsoDate, GetFunc = GetIsoDate };
|
|
||||||
|
|
||||||
private static DateTime GetIsoDate(string value)
|
private static DateTime GetIsoDate(string value)
|
||||||
{
|
{
|
||||||
@ -23,11 +23,10 @@ namespace Connected
|
|||||||
return value.ToIsoDateString();
|
return value.ToIsoDateString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Converter<DateTime?> NullableIsoDate
|
public static LambdaConverter<DateTime?, string?> NullableIsoDate
|
||||||
=> new()
|
=> new(SetNullableIsoDate, GetNullableIsoDate);
|
||||||
{ SetFunc = SetNullableIsoDate, GetFunc = GetNullableIsoDate };
|
|
||||||
|
|
||||||
private static DateTime? GetNullableIsoDate(string value)
|
private static DateTime? GetNullableIsoDate(string? value)
|
||||||
{
|
{
|
||||||
if (DateTime.TryParse(value, out var dateTime))
|
if (DateTime.TryParse(value, out var dateTime))
|
||||||
return dateTime;
|
return dateTime;
|
||||||
|
@ -6,18 +6,26 @@ namespace Connected
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// A ready made DateTime? to string binding converter with configurable date format and culture
|
/// A ready made DateTime? to string binding converter with configurable date format and culture
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class NullableDateConverter : Converter<DateTime?>
|
public class NullableDateConverter : ToStringConverter<DateTime?>
|
||||||
{
|
{
|
||||||
public string DateFormat { get; set; }
|
public string DateFormat { get; set; }
|
||||||
|
|
||||||
public NullableDateConverter(string format = "yyyy-MM-dd")
|
public NullableDateConverter(string format = "yyyy-MM-dd")
|
||||||
{
|
{
|
||||||
DateFormat = format;
|
DateFormat = format;
|
||||||
SetFunc = OnSet;
|
|
||||||
GetFunc = OnGet;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private DateTime? OnGet(string arg)
|
protected override string? ConvertValue(DateTime? value)
|
||||||
|
{
|
||||||
|
return OnSet(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override DateTime? ConvertValueBack(string? value)
|
||||||
|
{
|
||||||
|
return OnGet(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private DateTime? OnGet(string arg)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -25,7 +33,7 @@ namespace Connected
|
|||||||
}
|
}
|
||||||
catch (FormatException e)
|
catch (FormatException e)
|
||||||
{
|
{
|
||||||
UpdateGetError(e.Message);
|
TriggerError(e.Message);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -40,7 +48,7 @@ namespace Connected
|
|||||||
}
|
}
|
||||||
catch (FormatException e)
|
catch (FormatException e)
|
||||||
{
|
{
|
||||||
UpdateSetError(e.Message);
|
TriggerError(e.Message);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -49,18 +57,26 @@ namespace Connected
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// A ready made DateTime to string binding converter with configurable date format and culture
|
/// A ready made DateTime to string binding converter with configurable date format and culture
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class DateConverter : Converter<DateTime>
|
public class DateConverter : ToStringConverter<DateTime>
|
||||||
{
|
{
|
||||||
public string DateFormat { get; set; } = "yyyy-MM-dd";
|
public string DateFormat { get; set; } = "yyyy-MM-dd";
|
||||||
|
|
||||||
public DateConverter(string format)
|
public DateConverter(string format)
|
||||||
{
|
{
|
||||||
DateFormat = format;
|
DateFormat = format;
|
||||||
SetFunc = OnSet;
|
|
||||||
GetFunc = OnGet;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private DateTime OnGet(string arg)
|
protected override string? ConvertValue(DateTime value)
|
||||||
|
{
|
||||||
|
return OnSet(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override DateTime ConvertValueBack(string value)
|
||||||
|
{
|
||||||
|
return OnGet(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private DateTime OnGet(string arg)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -68,7 +84,7 @@ namespace Connected
|
|||||||
}
|
}
|
||||||
catch (FormatException e)
|
catch (FormatException e)
|
||||||
{
|
{
|
||||||
UpdateGetError(e.Message);
|
TriggerError(e.Message);
|
||||||
return default;
|
return default;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -81,7 +97,7 @@ namespace Connected
|
|||||||
}
|
}
|
||||||
catch (FormatException e)
|
catch (FormatException e)
|
||||||
{
|
{
|
||||||
UpdateSetError(e.Message);
|
TriggerError(e.Message);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,16 +7,24 @@ namespace Connected
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// A universal T to string binding converter
|
/// A universal T to string binding converter
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class DefaultConverter<T> : Converter<T>
|
public class DefaultConverter<T> : ToStringConverter<T>
|
||||||
{
|
{
|
||||||
|
|
||||||
public DefaultConverter()
|
public DefaultConverter()
|
||||||
{
|
{
|
||||||
SetFunc = ConvertToString;
|
|
||||||
GetFunc = ConvertFromString;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string DefaultTimeSpanFormat { get; set; } = "c";
|
protected override string? ConvertValue(T? value)
|
||||||
|
{
|
||||||
|
return ConvertToString(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override T? ConvertValueBack(string? value)
|
||||||
|
{
|
||||||
|
return ConvertFromString(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string DefaultTimeSpanFormat { get; set; } = "c";
|
||||||
|
|
||||||
protected virtual T ConvertFromString(string value)
|
protected virtual T ConvertFromString(string value)
|
||||||
{
|
{
|
||||||
@ -42,91 +50,91 @@ namespace Connected
|
|||||||
return (T)(object)true;
|
return (T)(object)true;
|
||||||
if (lowerValue is "false" or "off")
|
if (lowerValue is "false" or "off")
|
||||||
return (T)(object)false;
|
return (T)(object)false;
|
||||||
UpdateGetError("Not a valid boolean");
|
TriggerError("Not a valid boolean");
|
||||||
}
|
}
|
||||||
// sbyte
|
// sbyte
|
||||||
else if (typeof(T) == typeof(sbyte) || typeof(T) == typeof(sbyte?))
|
else if (typeof(T) == typeof(sbyte) || typeof(T) == typeof(sbyte?))
|
||||||
{
|
{
|
||||||
if (sbyte.TryParse(value, NumberStyles.Integer | NumberStyles.AllowThousands, Culture, out var parsedValue))
|
if (sbyte.TryParse(value, NumberStyles.Integer | NumberStyles.AllowThousands, Culture, out var parsedValue))
|
||||||
return (T)(object)parsedValue;
|
return (T)(object)parsedValue;
|
||||||
UpdateGetError("Not a valid number");
|
TriggerError("Not a valid number");
|
||||||
}
|
}
|
||||||
// byte
|
// byte
|
||||||
else if (typeof(T) == typeof(byte) || typeof(T) == typeof(byte?))
|
else if (typeof(T) == typeof(byte) || typeof(T) == typeof(byte?))
|
||||||
{
|
{
|
||||||
if (byte.TryParse(value, NumberStyles.Integer | NumberStyles.AllowThousands, Culture, out var parsedValue))
|
if (byte.TryParse(value, NumberStyles.Integer | NumberStyles.AllowThousands, Culture, out var parsedValue))
|
||||||
return (T)(object)parsedValue;
|
return (T)(object)parsedValue;
|
||||||
UpdateGetError("Not a valid number");
|
TriggerError("Not a valid number");
|
||||||
}
|
}
|
||||||
// short
|
// short
|
||||||
else if (typeof(T) == typeof(short) || typeof(T) == typeof(short?))
|
else if (typeof(T) == typeof(short) || typeof(T) == typeof(short?))
|
||||||
{
|
{
|
||||||
if (short.TryParse(value, NumberStyles.Integer | NumberStyles.AllowThousands, Culture, out var parsedValue))
|
if (short.TryParse(value, NumberStyles.Integer | NumberStyles.AllowThousands, Culture, out var parsedValue))
|
||||||
return (T)(object)parsedValue;
|
return (T)(object)parsedValue;
|
||||||
UpdateGetError("Not a valid number");
|
TriggerError("Not a valid number");
|
||||||
}
|
}
|
||||||
// ushort
|
// ushort
|
||||||
else if (typeof(T) == typeof(ushort) || typeof(T) == typeof(ushort?))
|
else if (typeof(T) == typeof(ushort) || typeof(T) == typeof(ushort?))
|
||||||
{
|
{
|
||||||
if (ushort.TryParse(value, NumberStyles.Integer | NumberStyles.AllowThousands, Culture, out var parsedValue))
|
if (ushort.TryParse(value, NumberStyles.Integer | NumberStyles.AllowThousands, Culture, out var parsedValue))
|
||||||
return (T)(object)parsedValue;
|
return (T)(object)parsedValue;
|
||||||
UpdateGetError("Not a valid number");
|
TriggerError("Not a valid number");
|
||||||
}
|
}
|
||||||
// int
|
// int
|
||||||
else if (typeof(T) == typeof(int) || typeof(T) == typeof(int?))
|
else if (typeof(T) == typeof(int) || typeof(T) == typeof(int?))
|
||||||
{
|
{
|
||||||
if (int.TryParse(value, NumberStyles.Integer | NumberStyles.AllowThousands, Culture, out var parsedValue))
|
if (int.TryParse(value, NumberStyles.Integer | NumberStyles.AllowThousands, Culture, out var parsedValue))
|
||||||
return (T)(object)parsedValue;
|
return (T)(object)parsedValue;
|
||||||
UpdateGetError("Not a valid number");
|
TriggerError("Not a valid number");
|
||||||
}
|
}
|
||||||
// uint
|
// uint
|
||||||
else if (typeof(T) == typeof(uint) || typeof(T) == typeof(uint?))
|
else if (typeof(T) == typeof(uint) || typeof(T) == typeof(uint?))
|
||||||
{
|
{
|
||||||
if (uint.TryParse(value, NumberStyles.Integer | NumberStyles.AllowThousands, Culture, out var parsedValue))
|
if (uint.TryParse(value, NumberStyles.Integer | NumberStyles.AllowThousands, Culture, out var parsedValue))
|
||||||
return (T)(object)parsedValue;
|
return (T)(object)parsedValue;
|
||||||
UpdateGetError("Not a valid number");
|
TriggerError("Not a valid number");
|
||||||
}
|
}
|
||||||
// long
|
// long
|
||||||
else if (typeof(T) == typeof(long) || typeof(T) == typeof(long?))
|
else if (typeof(T) == typeof(long) || typeof(T) == typeof(long?))
|
||||||
{
|
{
|
||||||
if (long.TryParse(value, NumberStyles.Integer | NumberStyles.AllowThousands, Culture, out var parsedValue))
|
if (long.TryParse(value, NumberStyles.Integer | NumberStyles.AllowThousands, Culture, out var parsedValue))
|
||||||
return (T)(object)parsedValue;
|
return (T)(object)parsedValue;
|
||||||
UpdateGetError("Not a valid number");
|
TriggerError("Not a valid number");
|
||||||
}
|
}
|
||||||
// ulong
|
// ulong
|
||||||
else if (typeof(T) == typeof(ulong) || typeof(T) == typeof(ulong?))
|
else if (typeof(T) == typeof(ulong) || typeof(T) == typeof(ulong?))
|
||||||
{
|
{
|
||||||
if (ulong.TryParse(value, NumberStyles.Integer | NumberStyles.AllowThousands, Culture, out var parsedValue))
|
if (ulong.TryParse(value, NumberStyles.Integer | NumberStyles.AllowThousands, Culture, out var parsedValue))
|
||||||
return (T)(object)parsedValue;
|
return (T)(object)parsedValue;
|
||||||
UpdateGetError("Not a valid number");
|
TriggerError("Not a valid number");
|
||||||
}
|
}
|
||||||
// float
|
// float
|
||||||
else if (typeof(T) == typeof(float) || typeof(T) == typeof(float?))
|
else if (typeof(T) == typeof(float) || typeof(T) == typeof(float?))
|
||||||
{
|
{
|
||||||
if (float.TryParse(value, NumberStyles.Any, Culture, out var parsedValue))
|
if (float.TryParse(value, NumberStyles.Any, Culture, out var parsedValue))
|
||||||
return (T)(object)parsedValue;
|
return (T)(object)parsedValue;
|
||||||
UpdateGetError("Not a valid number");
|
TriggerError("Not a valid number");
|
||||||
}
|
}
|
||||||
// double
|
// double
|
||||||
else if (typeof(T) == typeof(double) || typeof(T) == typeof(double?))
|
else if (typeof(T) == typeof(double) || typeof(T) == typeof(double?))
|
||||||
{
|
{
|
||||||
if (double.TryParse(value, NumberStyles.Any, Culture, out var parsedValue))
|
if (double.TryParse(value, NumberStyles.Any, Culture, out var parsedValue))
|
||||||
return (T)(object)parsedValue;
|
return (T)(object)parsedValue;
|
||||||
UpdateGetError("Not a valid number");
|
TriggerError("Not a valid number");
|
||||||
}
|
}
|
||||||
// decimal
|
// decimal
|
||||||
else if (typeof(T) == typeof(decimal) || typeof(T) == typeof(decimal?))
|
else if (typeof(T) == typeof(decimal) || typeof(T) == typeof(decimal?))
|
||||||
{
|
{
|
||||||
if (decimal.TryParse(value, NumberStyles.Any, Culture, out var parsedValue))
|
if (decimal.TryParse(value, NumberStyles.Any, Culture, out var parsedValue))
|
||||||
return (T)(object)parsedValue;
|
return (T)(object)parsedValue;
|
||||||
UpdateGetError("Not a valid number");
|
TriggerError("Not a valid number");
|
||||||
}
|
}
|
||||||
// guid
|
// guid
|
||||||
else if (typeof(T) == typeof(Guid) || typeof(T) == typeof(Guid?))
|
else if (typeof(T) == typeof(Guid) || typeof(T) == typeof(Guid?))
|
||||||
{
|
{
|
||||||
if (Guid.TryParse(value, out var parsedValue))
|
if (Guid.TryParse(value, out var parsedValue))
|
||||||
return (T)(object)parsedValue;
|
return (T)(object)parsedValue;
|
||||||
UpdateGetError("Not a valid GUID");
|
TriggerError("Not a valid GUID");
|
||||||
}
|
}
|
||||||
// enum
|
// enum
|
||||||
else if (IsNullableEnum(typeof(T)))
|
else if (IsNullableEnum(typeof(T)))
|
||||||
@ -134,13 +142,13 @@ namespace Connected
|
|||||||
var enum_type = Nullable.GetUnderlyingType(typeof(T));
|
var enum_type = Nullable.GetUnderlyingType(typeof(T));
|
||||||
if (Enum.TryParse(enum_type, value, out var parsedValue))
|
if (Enum.TryParse(enum_type, value, out var parsedValue))
|
||||||
return (T)parsedValue;
|
return (T)parsedValue;
|
||||||
UpdateGetError("Not a value of " + enum_type.Name);
|
TriggerError("Not a value of " + enum_type.Name);
|
||||||
}
|
}
|
||||||
else if (typeof(T).IsEnum)
|
else if (typeof(T).IsEnum)
|
||||||
{
|
{
|
||||||
if (Enum.TryParse(typeof(T), value, out var parsedValue))
|
if (Enum.TryParse(typeof(T), value, out var parsedValue))
|
||||||
return (T)parsedValue;
|
return (T)parsedValue;
|
||||||
UpdateGetError("Not a value of " + typeof(T).Name);
|
TriggerError("Not a value of " + typeof(T).Name);
|
||||||
}
|
}
|
||||||
// datetime
|
// datetime
|
||||||
else if (typeof(T) == typeof(DateTime) || typeof(T) == typeof(DateTime?))
|
else if (typeof(T) == typeof(DateTime) || typeof(T) == typeof(DateTime?))
|
||||||
@ -151,7 +159,7 @@ namespace Connected
|
|||||||
}
|
}
|
||||||
catch (FormatException)
|
catch (FormatException)
|
||||||
{
|
{
|
||||||
UpdateGetError("Not a valid date time");
|
TriggerError("Not a valid date time");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// timespan
|
// timespan
|
||||||
@ -163,17 +171,17 @@ namespace Connected
|
|||||||
}
|
}
|
||||||
catch (FormatException)
|
catch (FormatException)
|
||||||
{
|
{
|
||||||
UpdateGetError("Not a valid time span");
|
TriggerError("Not a valid time span");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
UpdateGetError($"Conversion to type {typeof(T)} not implemented");
|
TriggerError($"Conversion to type {typeof(T)} not implemented");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
UpdateGetError("Conversion error: " + e.Message);
|
TriggerError("Conversion error: " + e.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
return default(T);
|
return default(T);
|
||||||
@ -301,7 +309,7 @@ namespace Connected
|
|||||||
}
|
}
|
||||||
catch (FormatException e)
|
catch (FormatException e)
|
||||||
{
|
{
|
||||||
UpdateSetError("Conversion error: " + e.Message);
|
TriggerError("Conversion error: " + e.Message);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,11 +17,19 @@ namespace Connected
|
|||||||
|
|
||||||
public NumericConverter()
|
public NumericConverter()
|
||||||
{
|
{
|
||||||
SetFunc = OnSet;
|
|
||||||
GetFunc = OnGet;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private T OnGet(double value)
|
protected override double ConvertValue(T? value)
|
||||||
|
{
|
||||||
|
return OnSet(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override T? ConvertValueBack(double value)
|
||||||
|
{
|
||||||
|
return OnGet(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private T OnGet(double value)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -33,42 +41,42 @@ namespace Connected
|
|||||||
return (T)(object)value.ToString(Culture);
|
return (T)(object)value.ToString(Culture);
|
||||||
// sbyte
|
// sbyte
|
||||||
else if (typeof(T) == typeof(sbyte) || typeof(T) == typeof(sbyte?))
|
else if (typeof(T) == typeof(sbyte) || typeof(T) == typeof(sbyte?))
|
||||||
return (T)(object)Convert.ToSByte(value);
|
return (T)(object)System.Convert.ToSByte(value);
|
||||||
// byte
|
// byte
|
||||||
else if (typeof(T) == typeof(byte) || typeof(T) == typeof(byte?))
|
else if (typeof(T) == typeof(byte) || typeof(T) == typeof(byte?))
|
||||||
return (T)(object)Convert.ToByte(value);
|
return (T)(object)System.Convert.ToByte(value);
|
||||||
// short
|
// short
|
||||||
else if (typeof(T) == typeof(short) || typeof(T) == typeof(short?))
|
else if (typeof(T) == typeof(short) || typeof(T) == typeof(short?))
|
||||||
return (T)(object)Convert.ToInt16(value);
|
return (T)(object)System.Convert.ToInt16(value);
|
||||||
// ushort
|
// ushort
|
||||||
else if (typeof(T) == typeof(ushort) || typeof(T) == typeof(ushort?))
|
else if (typeof(T) == typeof(ushort) || typeof(T) == typeof(ushort?))
|
||||||
return (T)(object)Convert.ToUInt16(value);
|
return (T)(object)System.Convert.ToUInt16(value);
|
||||||
// int
|
// int
|
||||||
else if (typeof(T) == typeof(int) || typeof(T) == typeof(int?))
|
else if (typeof(T) == typeof(int) || typeof(T) == typeof(int?))
|
||||||
return (T)(object)Convert.ToInt32(value);
|
return (T)(object)System.Convert.ToInt32(value);
|
||||||
// uint
|
// uint
|
||||||
else if (typeof(T) == typeof(uint) || typeof(T) == typeof(uint?))
|
else if (typeof(T) == typeof(uint) || typeof(T) == typeof(uint?))
|
||||||
return (T)(object)Convert.ToUInt32(value);
|
return (T)(object)System.Convert.ToUInt32(value);
|
||||||
// long
|
// long
|
||||||
else if (typeof(T) == typeof(long) || typeof(T) == typeof(long?))
|
else if (typeof(T) == typeof(long) || typeof(T) == typeof(long?))
|
||||||
return (T)(object)Convert.ToInt64(value);
|
return (T)(object)System.Convert.ToInt64(value);
|
||||||
// ulong
|
// ulong
|
||||||
else if (typeof(T) == typeof(ulong) || typeof(T) == typeof(ulong?))
|
else if (typeof(T) == typeof(ulong) || typeof(T) == typeof(ulong?))
|
||||||
return (T)(object)Convert.ToUInt64(value);
|
return (T)(object)System.Convert.ToUInt64(value);
|
||||||
// float
|
// float
|
||||||
else if (typeof(T) == typeof(float) || typeof(T) == typeof(float?))
|
else if (typeof(T) == typeof(float) || typeof(T) == typeof(float?))
|
||||||
return (T)(object)Convert.ToSingle(value);
|
return (T)(object)System.Convert.ToSingle(value);
|
||||||
// decimal
|
// decimal
|
||||||
else if (typeof(T) == typeof(decimal) || typeof(T) == typeof(decimal?))
|
else if (typeof(T) == typeof(decimal) || typeof(T) == typeof(decimal?))
|
||||||
return (T)(object)Convert.ToDecimal(value);
|
return (T)(object)System.Convert.ToDecimal(value);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
UpdateGetError($"Conversion to type {typeof(T)} not implemented");
|
TriggerError($"Conversion to type {typeof(T)} not implemented");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
UpdateGetError("Conversion error: " + e.Message);
|
TriggerError("Conversion error: " + e.Message);
|
||||||
return default(T);
|
return default(T);
|
||||||
}
|
}
|
||||||
return default(T);
|
return default(T);
|
||||||
@ -90,63 +98,63 @@ namespace Connected
|
|||||||
return double.Parse((string)(object)arg, NumberStyles.Any, Culture);
|
return double.Parse((string)(object)arg, NumberStyles.Any, Culture);
|
||||||
// sbyte
|
// sbyte
|
||||||
if (typeof(T) == typeof(sbyte))
|
if (typeof(T) == typeof(sbyte))
|
||||||
return Convert.ToDouble((sbyte)(object)arg);
|
return System.Convert.ToDouble((sbyte)(object)arg);
|
||||||
if (typeof(T) == typeof(sbyte?))
|
if (typeof(T) == typeof(sbyte?))
|
||||||
return Convert.ToDouble(((sbyte?)(object)arg).Value);
|
return System.Convert.ToDouble(((sbyte?)(object)arg).Value);
|
||||||
// byte
|
// byte
|
||||||
if (typeof(T) == typeof(byte))
|
if (typeof(T) == typeof(byte))
|
||||||
return Convert.ToDouble((byte)(object)arg);
|
return System.Convert.ToDouble((byte)(object)arg);
|
||||||
if (typeof(T) == typeof(byte?))
|
if (typeof(T) == typeof(byte?))
|
||||||
return Convert.ToDouble(((byte?)(object)arg).Value);
|
return System.Convert.ToDouble(((byte?)(object)arg).Value);
|
||||||
// short
|
// short
|
||||||
if (typeof(T) == typeof(short))
|
if (typeof(T) == typeof(short))
|
||||||
return Convert.ToDouble((short)(object)arg);
|
return System.Convert.ToDouble((short)(object)arg);
|
||||||
if (typeof(T) == typeof(short?))
|
if (typeof(T) == typeof(short?))
|
||||||
return Convert.ToDouble(((short?)(object)arg).Value);
|
return System.Convert.ToDouble(((short?)(object)arg).Value);
|
||||||
// ushort
|
// ushort
|
||||||
if (typeof(T) == typeof(ushort))
|
if (typeof(T) == typeof(ushort))
|
||||||
return Convert.ToDouble((ushort)(object)arg);
|
return System.Convert.ToDouble((ushort)(object)arg);
|
||||||
if (typeof(T) == typeof(ushort?))
|
if (typeof(T) == typeof(ushort?))
|
||||||
return Convert.ToDouble(((ushort?)(object)arg).Value);
|
return System.Convert.ToDouble(((ushort?)(object)arg).Value);
|
||||||
// int
|
// int
|
||||||
else if (typeof(T) == typeof(int))
|
else if (typeof(T) == typeof(int))
|
||||||
return Convert.ToDouble((int)(object)arg);
|
return System.Convert.ToDouble((int)(object)arg);
|
||||||
else if (typeof(T) == typeof(int?))
|
else if (typeof(T) == typeof(int?))
|
||||||
return Convert.ToDouble(((int?)(object)arg).Value);
|
return System.Convert.ToDouble(((int?)(object)arg).Value);
|
||||||
// uint
|
// uint
|
||||||
else if (typeof(T) == typeof(uint))
|
else if (typeof(T) == typeof(uint))
|
||||||
return Convert.ToDouble((uint)(object)arg);
|
return System.Convert.ToDouble((uint)(object)arg);
|
||||||
else if (typeof(T) == typeof(uint?))
|
else if (typeof(T) == typeof(uint?))
|
||||||
return Convert.ToDouble(((uint?)(object)arg).Value);
|
return System.Convert.ToDouble(((uint?)(object)arg).Value);
|
||||||
// long
|
// long
|
||||||
else if (typeof(T) == typeof(long))
|
else if (typeof(T) == typeof(long))
|
||||||
return Convert.ToDouble((long)(object)arg);
|
return System.Convert.ToDouble((long)(object)arg);
|
||||||
else if (typeof(T) == typeof(long?))
|
else if (typeof(T) == typeof(long?))
|
||||||
return Convert.ToDouble(((long?)(object)arg).Value);
|
return System.Convert.ToDouble(((long?)(object)arg).Value);
|
||||||
// ulong
|
// ulong
|
||||||
else if (typeof(T) == typeof(ulong))
|
else if (typeof(T) == typeof(ulong))
|
||||||
return Convert.ToDouble((ulong)(object)arg);
|
return System.Convert.ToDouble((ulong)(object)arg);
|
||||||
else if (typeof(T) == typeof(ulong?))
|
else if (typeof(T) == typeof(ulong?))
|
||||||
return Convert.ToDouble(((ulong?)(object)arg).Value);
|
return System.Convert.ToDouble(((ulong?)(object)arg).Value);
|
||||||
// float
|
// float
|
||||||
else if (typeof(T) == typeof(float))
|
else if (typeof(T) == typeof(float))
|
||||||
return Convert.ToDouble((float)(object)arg);
|
return System.Convert.ToDouble((float)(object)arg);
|
||||||
else if (typeof(T) == typeof(float?))
|
else if (typeof(T) == typeof(float?))
|
||||||
return Convert.ToDouble(((float?)(object)arg).Value);
|
return System.Convert.ToDouble(((float?)(object)arg).Value);
|
||||||
// decimal
|
// decimal
|
||||||
else if (typeof(T) == typeof(decimal))
|
else if (typeof(T) == typeof(decimal))
|
||||||
return Convert.ToDouble((decimal)(object)arg);
|
return System.Convert.ToDouble((decimal)(object)arg);
|
||||||
else if (typeof(T) == typeof(decimal?))
|
else if (typeof(T) == typeof(decimal?))
|
||||||
return Convert.ToDouble(((decimal?)(object)arg).Value);
|
return System.Convert.ToDouble(((decimal?)(object)arg).Value);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
UpdateSetError("Unable to convert to double from type " + typeof(T).Name);
|
TriggerError("Unable to convert to double from type " + typeof(T).Name);
|
||||||
return double.NaN;
|
return double.NaN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (FormatException e)
|
catch (FormatException e)
|
||||||
{
|
{
|
||||||
UpdateSetError("Conversion error: " + e.Message);
|
TriggerError("Conversion error: " + e.Message);
|
||||||
return double.NaN;
|
return double.NaN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,61 +1,69 @@
|
|||||||
namespace Connected
|
using Connected.Components;
|
||||||
|
|
||||||
|
namespace Connected;
|
||||||
|
|
||||||
|
public class RangeConverter<T> : ToStringConverter<Range<T>>
|
||||||
{
|
{
|
||||||
public class RangeConverter<T> : Converter<Components.Range<T>>
|
readonly DefaultConverter<T> _converter;
|
||||||
{
|
|
||||||
readonly DefaultConverter<T> _converter;
|
|
||||||
|
|
||||||
public RangeConverter()
|
public RangeConverter()
|
||||||
{
|
{
|
||||||
_converter = new DefaultConverter<T>();
|
_converter = new DefaultConverter<T>();
|
||||||
|
}
|
||||||
|
|
||||||
SetFunc = OnSet;
|
protected override string? ConvertValue(Range<T>? value)
|
||||||
GetFunc = OnGet;
|
{
|
||||||
}
|
return OnSet(value);
|
||||||
|
}
|
||||||
|
|
||||||
private Components.Range<T> OnGet(string value)
|
protected override Range<T>? ConvertValueBack(string? value)
|
||||||
{
|
{
|
||||||
if (!Split(value, out var valueStart, out var valueEnd))
|
return OnGet(value);
|
||||||
return null;
|
}
|
||||||
|
|
||||||
return new Components.Range<T>(_converter.Get(valueStart), _converter.Get(valueEnd));
|
private Range<T> OnGet(string value)
|
||||||
}
|
{
|
||||||
|
if (!Split(value, out var valueStart, out var valueEnd))
|
||||||
|
return null;
|
||||||
|
|
||||||
private string OnSet(Components.Range<T> arg)
|
return new Range<T>(_converter.ConvertBack(valueStart), _converter.ConvertBack(valueEnd));
|
||||||
{
|
}
|
||||||
if (arg == null)
|
|
||||||
return string.Empty;
|
|
||||||
|
|
||||||
return Join(_converter.Set(arg.Start), _converter.Set(arg.End));
|
private string OnSet(Range<T> arg)
|
||||||
}
|
{
|
||||||
|
if (arg == null)
|
||||||
|
return string.Empty;
|
||||||
|
|
||||||
public static string Join(string valueStart, string valueEnd)
|
return Join(_converter.Convert(arg.Start), _converter.Convert(arg.End));
|
||||||
{
|
}
|
||||||
if (string.IsNullOrEmpty(valueStart) && string.IsNullOrEmpty(valueEnd))
|
|
||||||
return string.Empty;
|
|
||||||
|
|
||||||
return $"[{valueStart};{valueEnd}]";
|
public static string Join(string valueStart, string valueEnd)
|
||||||
}
|
{
|
||||||
|
if (string.IsNullOrEmpty(valueStart) && string.IsNullOrEmpty(valueEnd))
|
||||||
|
return string.Empty;
|
||||||
|
|
||||||
public static bool Split(string value, out string valueStart, out string valueEnd)
|
return $"[{valueStart};{valueEnd}]";
|
||||||
{
|
}
|
||||||
valueStart = valueEnd = string.Empty;
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(value) || value[0] != '[' || value[^1] != ']')
|
public static bool Split(string value, out string valueStart, out string valueEnd)
|
||||||
{
|
{
|
||||||
return false;
|
valueStart = valueEnd = string.Empty;
|
||||||
}
|
|
||||||
|
|
||||||
var idx = value.IndexOf(';');
|
if (string.IsNullOrEmpty(value) || value[0] != '[' || value[^1] != ']')
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (idx < 1)
|
var idx = value.IndexOf(';');
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
valueStart = value[1..idx];
|
if (idx < 1)
|
||||||
valueEnd = value[(idx + 1)..^1];
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
valueStart = value[1..idx];
|
||||||
}
|
valueEnd = value[(idx + 1)..^1];
|
||||||
}
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user