Skip to content

Instantly share code, notes, and snippets.

@udaken
Last active March 14, 2020 10:33
Show Gist options
  • Save udaken/48f2714a5bd12a5932cc868d93fc256f to your computer and use it in GitHub Desktop.
Save udaken/48f2714a5bd12a5932cc868d93fc256f to your computer and use it in GitHub Desktop.
using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
#nullable enable
struct NotifiableProperty<T>
{
private readonly IEqualityComparer<T> _EqualityComparer;
private readonly PropertyChangedEventArgs _ChangedEventArgs;
#if SUPPORT_PROPERTY_CHANGING
private readonly PropertyChangingEventArgs _ChangingEventArgs;
#endif
public T Value
{
readonly get;
private set;
}
private readonly IEnumerable<PropertyChangedEventArgs>? _DependedPropertiesChangedEventArgs;
#if SUPPORT_PROPERTY_CHANGING
private readonly IEnumerable<PropertyChangingEventArgs>? _DependedPropertiesChangingEventArgs;
#endif
public NotifiableProperty(string name, T initValue = default, IEqualityComparer<T>? equalityComparer = null)
: this(name, initValue, equalityComparer ?? EqualityComparer<T>.Default, null)
{
}
public NotifiableProperty(string name, T initValue, params string[] dependedPropertyNames)
: this(name, initValue, EqualityComparer<T>.Default, dependedPropertyNames)
{
}
public NotifiableProperty(string name, T initValue, IEqualityComparer<T> equalityComparer, params string[]? dependedPropertyNames)
{
if (name == null)
throw new ArgumentNullException(nameof(name));
_ChangedEventArgs = new PropertyChangedEventArgs(name);
#if SUPPORT_PROPERTY_CHANGING
_ChangingEventArgs = new PropertyChangingEventArgs(name);
#endif
Value = initValue;
_DependedPropertiesChangedEventArgs = dependedPropertyNames?.Select(name => new PropertyChangedEventArgs(name));
#if SUPPORT_PROPERTY_CHANGING
_DependedPropertiesChangingEventArgs = dependedPropertyNames?.Select(name => new PropertyChangingEventArgs(name));
#endif
_EqualityComparer = equalityComparer ?? throw new ArgumentNullException(nameof(equalityComparer));
}
public bool SetValue(PropertyChangedEventHandler? propertyChanged, T value, object? sender = null)
#if SUPPORT_PROPERTY_CHANGING
=> SetValue(propertyChanged, null, value, sender);
public bool SetValue(PropertyChangingEventHandler? propertyChanging, T value) => SetValue(null, propertyChanging, value, object? sender = null);
public bool SetValue(PropertyChangedEventHandler? propertyChanged, PropertyChangingEventHandler? propertyChanging, T value, object? sender = null)
#endif
{
if (!_EqualityComparer.Equals(Value, value))
{
#if SUPPORT_PROPERTY_CHANGING
propertyChanging?.Invoke(this, _ChangingEventArgs);
if (_DependedPropertiesChangingEventArgs != null)
{
foreach (var eventArgs in _DependedPropertiesChangingEventArgs)
{
propertyChanging?.Invoke(this, eventArgs);
}
}
#endif
Value = value;
propertyChanged?.Invoke(sender, _ChangedEventArgs);
if (_DependedPropertiesChangedEventArgs != null)
{
foreach (var eventArgs in _DependedPropertiesChangedEventArgs)
{
propertyChanged?.Invoke(sender, eventArgs);
}
}
return true;
}
return false;
}
public static implicit operator T(in NotifiableProperty<T> self) => self.Value;
}
static class NotifiableProperty
{
public static NotifiableProperty<T> Make<T>(string name, T initValue, IEqualityComparer<T>? equalityComparer = null)
=> new NotifiableProperty<T>(name, initValue, equalityComparer);
public static NotifiableProperty<T> Make<T>(string name, T initValue, IEqualityComparer<T> equalityComparer, params string[] dependedPropertyNames)
=> new NotifiableProperty<T>(name, initValue, equalityComparer, dependedPropertyNames);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment