public class Identifier : IComparable { private object Value; public Identifier(object value) { Value = value; } public override bool Equals(object obj) { if (obj == null || GetType() != obj.GetType()) return false; var other = (Identifier)obj; return EqualityComparer<object>.Default.Equals(Value, other.Value); } public object GetValue() => Value; public static bool operator ==(Identifier id1, Identifier id2) { if (ReferenceEquals(id1, id2)) return true; if (id1 is null || id2 is null) return false; return id1.Equals(id2); } public static bool operator !=(Identifier id1, Identifier id2) => !(id1 == id2); public override int GetHashCode() => Value.GetHashCode(); public int CompareTo(object other) => InternalCompareTo(other); private int InternalCompareTo(object o) => CompareTo(o); public static Identifier From(string o) => string.IsNullOrWhiteSpace(o) ? null : new SpecificIdentifier<string>(o); public static Identifier From(Guid? o) => (o == null || o == Guid.Empty) ? null : new SpecificIdentifier<Guid>(o.Value); public static Identifier From(int? o) => (o == null) ? null : new SpecificIdentifier<int>(o.Value); class SpecificIdentifier<T> : Identifier { public T TypedValue { get; private set; } public SpecificIdentifier(T value) : base(value) { TypedValue = value; } } } public class IdentifierConverter : JsonConverter<Identifier> { public override void WriteJson(JsonWriter writer, Identifier value, JsonSerializer serializer) { serializer.Serialize(writer, value.GetValue()); } public override Identifier ReadJson(JsonReader reader, Type objectType, Identifier existingValue, bool hasExistingValue, JsonSerializer serializer) { var token = JToken.Load(reader); if (token is JValue valueWrapper) { var valueType = valueWrapper.Type; return valueType switch { JTokenType.Integer => Identifier.From((int)valueWrapper.Value), JTokenType.Guid => Identifier.From((Guid)valueWrapper.Value), JTokenType.String => Identifier.From((string)valueWrapper.Value), _ => null }; } return null; } }
961600cookie-checkC# Swappable identifiers