using R3; using System.ComponentModel.DataAnnotations; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text.Json; using System.Text.Json.Serialization; using System.Text.Json.Serialization.Metadata; // CollectionsMarshal.GetValueRef var v = new ClampedReactiveProperty2(5, 10, 30); Console.WriteLine(v.Value); public sealed class ClampedReactiveProperty(T initialValue, T min, T max) : ReactiveProperty(initialValue) where T : IComparable { private static IComparer Comparer { get; } = Comparer.Default; protected override void OnValueChanging(ref T value) { if (Comparer.Compare(value, min) < 0) { value = min; } else if (Comparer.Compare(value, max) > 0) { value = max; } } } public sealed class ClampedReactiveProperty2 : ReactiveProperty where T : IComparable { private static IComparer Comparer { get; } = Comparer.Default; readonly T min, max; // callOnValueChangeInBaseConstructor to avoid OnValueChanging call before min, max set. public ClampedReactiveProperty2(T initialValue, T min, T max) : base(initialValue, EqualityComparer.Default, callOnValueChangeInBaseConstructor: false) { this.min = min; this.max = max; // modify currentValue manually OnValueChanging(ref GetValueRef()); } protected override void OnValueChanging(ref T value) { if (Comparer.Compare(value, min) < 0) { value = min; } else if (Comparer.Compare(value, max) > 0) { value = max; } } } //[JsonConverter(typeof(IgnoreCaseStringReactivePropertyJsonConverter))] public class IgnoreCaseStringReactiveProperty : ReactiveProperty { public IgnoreCaseStringReactiveProperty(string value) : base(value, StringComparer.OrdinalIgnoreCase) { } } internal class IgnoreCaseStringReactivePropertyJsonConverter : ReactivePropertyJsonConverter { protected override ReactiveProperty CreateReactiveProperty(string value) { return new IgnoreCaseStringReactiveProperty(value); } }