using System.Globalization; namespace Connected; public class Converter { public event EventHandler? ErrorOccured; /// /// The culture info being used for decimal points, date and time format, etc. /// public CultureInfo Culture { get; set; } = Converters.DefaultCulture; public TDestinationType? Convert(TSourceType value) { try { 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) { } } /// /// Converts values using the supplied lambda functions. /// /// The source type /// The destination type public class LambdaConverter :Converter { private readonly Func? _convertFunction; private readonly Func? _convertBackFunction; public LambdaConverter(Func? convertFunction = null, Func? 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); } } /// /// Converter from T to string /// /// Set converts to string /// Get converts from string /// public class ToStringConverter : Converter { /// /// Custom Format to be applied on bidirectional way. /// public string? Format { get; set; } = null; }