我正在编写一个设置页面来将 IP 设置为以太网设备。
我在页面中放置了一个文本框和一个应用按钮。在文本框中输入 IP 并单击“应用”按钮后,将 IP 设置为设备。
现在我需要验证 TextBox 中的文本是否是 IP 地址。
这是我的代码:
public partial class EthernetConnection : ObservableObject
{
string _IP = "";
[IPAddress]
public string IP {
get => _IP;
set {
if (_IP != value)
{
_IP = value;
OnPropertyChanged();
}
}
}
public sealed class IPAddressAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
string _pattern = @"^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$";
if (value is string _string && Regex.IsMatch(_string, _pattern))
{
return ValidationResult.Success;
}
return new("Failed");
}
}
}
而且效果很好,当TextBox中输入的不是IP地址时,TextBox会提示你。
但是现在我遇到了一个问题。当点击Apply按钮时,我必须编写额外的代码来重新检查TextBox中的文本是否是IP地址,这很麻烦。
有没有办法让我直接检测属性是否已验证?
我会使用
Maybe<T>
而不是属性。
public class Maybe<T>
{
public class MissingValueException : Exception { }
public readonly static Maybe<T> Nothing = new Maybe<T>();
private T _value;
public T Value
{
get
{
if (!this.HasValue)
{
throw new MissingValueException();
}
return _value;
}
private set
{
_value = value;
}
}
public bool HasValue { get; private set; }
public Maybe()
{
HasValue = false;
}
public Maybe(T value)
{
Value = value;
HasValue = true;
}
public T ValueOrDefault() => this.HasValue ? this.Value : default(T);
public T ValueOrDefault(T @default) => this.HasValue ? this.Value : @default;
public T ValueOrDefault(Func<T> @default) => this.HasValue ? this.Value : @default();
public static implicit operator Maybe<T>(T v)
{
return v.ToMaybe();
}
public override string ToString()
{
return this.HasValue ? this.Value.ToString() : "()";
}
public override bool Equals(object obj)
{
if (obj is Maybe<T>)
return Equals((Maybe<T>)obj);
return false;
}
public bool Equals(Maybe<T> obj)
{
if (obj == null) return false;
if (!EqualityComparer<T>.Default.Equals(_value, obj._value)) return false;
if (!EqualityComparer<bool>.Default.Equals(this.HasValue, obj.HasValue)) return false;
return true;
}
public override int GetHashCode()
{
int hash = 0;
hash ^= EqualityComparer<T>.Default.GetHashCode(_value);
hash ^= EqualityComparer<bool>.Default.GetHashCode(this.HasValue);
return hash;
}
public static bool operator ==(Maybe<T> left, Maybe<T> right)
{
if (object.ReferenceEquals(left, null))
{
return object.ReferenceEquals(right, null);
}
return left.Equals(right);
}
public static bool operator !=(Maybe<T> left, Maybe<T> right)
{
return !(left == right);
}
}
然后这样做:
public partial class EthernetConnection : ObservableObject
{
public Maybe<string> MaybeIP { get; private set; } = "";
public string IP
{
set
{
string _pattern = @"^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$";
if (MaybeIP.HasValue && MaybeIP.Value != value)
{
MaybeIP = Regex.IsMatch(value, _pattern) ? value : Maybe<string>.Nothing;
OnPropertyChanged();
}
}
}
}
现在就像
Nullable<T>
,但适用于所有类型。
这里有一些方便的扩展方法,可以让它变得更好:
public static class MaybeEx
{
public static Maybe<T> ToMaybe<T>(this T value)
{
return new Maybe<T>(value);
}
public static T GetValue<T>(this Maybe<T> m, T @default) => m.HasValue ? m.Value : @default;
public static T GetValue<T>(this Maybe<T> m, Func<T> @default) => m.HasValue ? m.Value : @default();
public static Maybe<U> Select<T, U>(this Maybe<T> m, Func<T, U> k)
{
return m.SelectMany(t => k(t).ToMaybe());
}
public static Maybe<U> SelectMany<T, U>(this Maybe<T> m, Func<T, Maybe<U>> k)
{
if (!m.HasValue)
{
return Maybe<U>.Nothing;
}
return k(m.Value);
}
public static Maybe<V> SelectMany<T, U, V>(this Maybe<T> @this, Func<T, Maybe<U>> k, Func<T, U, V> s)
{
return @this.SelectMany(x => k(x).SelectMany(y => s(x, y).ToMaybe()));
}
public static Maybe<V> Maybe<K, V>(this IDictionary<K, V> @this, K key) => (@this.ContainsKey(key)) ? @this[key].ToMaybe() : Maybe<V>.Nothing;
}