namespace CommonConsole { using CommonConsole.JsonConverters; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; public abstract class Unit { public const int MsInSec = 1000; public const int SecInMin = 60; public const int MinInH = 60; public const int HInDay = 24; public const int MlInL = 1000; public const int LInm3 = 1000; public const int PInBar = 100000; public const int MAInH = 1000; protected double value; public virtual object Base { get; set; } public override string ToString() => this.value.ToString(); public override bool Equals(object obj) => this.value.Equals(obj); public override int GetHashCode() => this.value.GetHashCode(); public static implicit operator double (Unit @base) => @base?.value ?? default(double); public static implicit operator double? (Unit @base) => @base?.value; public static implicit operator Unit(string unitName) { try { var valueType = Type.GetType( typeName: $"CommonConsole.{unitName}", throwOnError: false, ignoreCase: true); var instance = Activator.CreateInstance(valueType); if (instance is Unit unit) { return unit; } } catch (Exception e) { // TODO: Handle exceptions. } return default(Unit); } public static IEnumerable MessurementUnits => typeof(Unit) .Assembly .GetTypes() .Where(x => typeof(Unit).IsAssignableFrom(x) && !x.IsAbstract) .Select(x => x.Name); } [JsonConverter(typeof(CurrentConverter))] public class Current : Unit { public double MiliampereHours { get => this.AmpereHours * MAInH; set => this.AmpereHours = value / MAInH; } public double AmpereHours { get => this.value; set => this.value = value; } public static implicit operator Current(double x) => new Current { value = x }; public static implicit operator Current(double? x) => new Current { value = x ?? 0 }; } [JsonConverter(typeof(FlowConverter))] public class Flow : Unit { public double CubicMeterInHour { get => this.value; set => this.value = value; } public double LiterInMinute { get => this.CubicMeterInHour / MinInH * LInm3; set => this.CubicMeterInHour = value * MinInH / LInm3; } public static implicit operator Flow(double x) => new Flow { value = x }; public static implicit operator Flow(double? x) => new Flow { value = x ?? 0 }; } [JsonConverter(typeof(PressureConverter))] public class Pressure : Unit { public double Pascal { get => this.value; set => this.value = value; } public double Bar { get => this.Pascal / PInBar; set => this.Pascal = value * PInBar; } public static implicit operator Pressure(double x) => new Pressure { value = x }; public static implicit operator Pressure(double? x) => new Pressure { value = x ?? 0 }; } [JsonConverter(typeof(TemperatureConverter))] public class Temperature : Unit { public double Celsius { get => this.value; set => this.value = value; } public static implicit operator Temperature(double x) => new Temperature { value = x }; public static implicit operator Temperature(double? x) => new Temperature { value = x ?? 0 }; } [JsonConverter(typeof(TimeConverter))] public class Time : Unit { public double Miliseconds { get => this.Seconds * MsInSec; set => this.Seconds = value / MsInSec; } public double Seconds { get => this.value; set => this.value = value; } public double Minutes { get => this.Seconds / SecInMin; set => this.Seconds = value * SecInMin; } public double Hours { get => this.Minutes / MinInH; set => this.Minutes = value * MinInH; } public double Days { get => this.Hours / HInDay; set => this.Hours = value * HInDay; } public static implicit operator Time(double x) => new Time { value = x }; public static implicit operator Time(double? x) => new Time { value = x ?? 0 }; } [JsonConverter(typeof(VolumeConverter))] public class Volume : Unit { public double Mililiter { get => this.Liter * MlInL; set => this.Liter = value / MlInL; } public double Liter { get => this.value * LInm3; set => this.value = value / LInm3; } public double CubicMeter { get => this.value * this.Factor; set => this.value = value / this.Factor; } public int Factor { get; set; } = 1000; public static implicit operator Volume(double x) => new Volume { value = x }; public static implicit operator Volume(double? x) => new Volume { value = x ?? 0 }; } }