using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Management; using System.Security.Cryptography; using System.Text; namespace Pilz.Cryptography { [JsonConverter(typeof(Json.Converters.UniquieIDStringJsonConverter))] public class UniquieID : IUniquieID { protected static ulong currentSimpleID = 0; [JsonProperty(nameof(ID))] protected string _iD; [JsonIgnore] public virtual bool SimpleMode { get; } [JsonIgnore] public virtual bool GenerateOnGet { get; } [JsonIgnore] public virtual bool HasID => !string.IsNullOrEmpty(_iD); [JsonIgnore] public virtual string ID { get { if (GenerateOnGet) GenerateIfNull(); return _iD; } internal set => _iD = value; } public UniquieID() : this(UniquieIDGenerationMode.None) { } public UniquieID(UniquieIDGenerationMode mode) : this(mode, false) { } public UniquieID(UniquieIDGenerationMode mode, bool simpleMode) { SimpleMode = simpleMode; if (mode == UniquieIDGenerationMode.GenerateOnInit) GenerateIfNull(); else if (mode == UniquieIDGenerationMode.GenerateOnGet) GenerateOnGet = true; } [Obsolete] public UniquieID(bool autoGenerate) : this(autoGenerate ? UniquieIDGenerationMode.GenerateOnInit : UniquieIDGenerationMode.None) { } public virtual void Generate() { if (SimpleMode) ID = GenerateSimple(); else ID = GenerateDefault(); } protected virtual string GenerateSimple() { return new Random().Next().ToString() + DateTime.Now.ToString("yyyyMMddHHmmssfffffff") + currentSimpleID++.ToString(); } protected virtual string GenerateDefault() { return GenerateUniquieID(currentSimpleID++.ToString()); } public virtual void GenerateIfNull() { if (!HasID) Generate(); } public override string ToString() { return ID; } public override int GetHashCode() { return -1430039477 + EqualityComparer.Default.GetHashCode(_iD); } public override bool Equals(object obj) { if (obj is UniquieID iD) { if (ReferenceEquals(obj, iD)) return true; else { var leftHasID = iD.HasID; var rightHasID = HasID; if (!leftHasID && iD.GenerateOnGet) { iD.Generate(); leftHasID = iD.HasID; } if (!rightHasID && GenerateOnGet) { Generate(); rightHasID = HasID; } if (leftHasID && rightHasID) return _iD.Equals(iD._iD); } } return base.Equals(obj); } #region Statics for Generation protected static string GenerateUniquieID(string var) { var sn = TryGetSerialNumberOfFirstHardDrive(); var dateTime = DateTime.UtcNow.ToString("yyyyMMddHHmmssfffffff"); var type = typeof(T).ToString(); var together = sn + dateTime + type + var; var md5 = MD5.Create(); var hash = BitConverter.ToString(md5.ComputeHash(Encoding.Default.GetBytes(together))).Replace("-", string.Empty); md5.Dispose(); return hash; } private static string Win32_PhysicalMedia_SerialNumber = null; private static string TryGetSerialNumberOfFirstHardDrive() { if (Win32_PhysicalMedia_SerialNumber == null) { var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_PhysicalMedia"); var sn = string.Empty; foreach (ManagementObject wmi_HD in searcher.Get()) { if (string.IsNullOrEmpty(sn) && wmi_HD["SerialNumber"] != null) sn = wmi_HD["SerialNumber"].ToString().Trim(); } Win32_PhysicalMedia_SerialNumber = sn; } return Win32_PhysicalMedia_SerialNumber; } #endregion public static implicit operator string(UniquieID id) => id.ID; public static implicit operator UniquieID(string id) => new UniquieID() { ID = id }; public static implicit operator UniquieID(int id) => new UniquieID() { ID = Convert.ToString(id) }; public static bool operator ==(UniquieID left, UniquieID right) => left.ID.Equals(right.ID); public static bool operator !=(UniquieID left, UniquieID right) => !left.ID.Equals(right.ID); } }