Skip to content

Instantly share code, notes, and snippets.

@runceel

runceel/IsModified.cs

Last active Apr 22, 2021
Embed
What would you like to do?
using Reactive.Bindings;
using Reactive.Bindings.Extensions;
using System;
using System.Linq;
using System.Reactive;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Reactive.Subjects;
namespace ConsoleApp5
{
class Program
{
static void Main(string[] args)
{
var p = new Person();
// 未変更なので false
Console.WriteLine(p.IsModified.Value);
p.Name.Value = "xxx";
// 変更したので true
Console.WriteLine(p.IsModified.Value);
p.Reset();
// Reset したので false
Console.WriteLine(p.IsModified.Value);
}
}
class Person : IDisposable
{
private readonly CompositeDisposable _disposables = new CompositeDisposable();
private readonly ISubject<Unit> _resetNotifyer;
public IReadOnlyReactiveProperty<bool> IsModified { get; }
public ReactiveProperty<string> Name { get; } = new ReactiveProperty<string>();
public ReactiveProperty<int> Age { get; } = new ReactiveProperty<int>();
public Person()
{
(IsModified, _resetNotifyer) = ReactivePropertyUtils.CreateIsModifiedProperty(Name, Age);
_disposables.Add(Name);
_disposables.Add(Age);
_disposables.Add(IsModified);
}
public void Reset() => _resetNotifyer.OnNext(Unit.Default);
public void Dispose()
{
_disposables.Dispose();
}
}
static class ReactivePropertyUtils
{
/// <summary>
/// 受け取った ReactiveProperty に変更があったかどうかを保持する IReadOnlyReactiveProperty を作成する。
/// </summary>
/// <param name="properties">変更を監視する対象の ReactiveProperty</param>
/// <returns>変更があった場合に true になる IReadOnlyReactiveProperty と、false にリセットするための ISubject。ISubject に OnNext(Unit.Default) を呼び出すことで IsModified が false にリセットされます。</returns>
public static (IReadOnlyReactiveProperty<bool> IsModified, ISubject<Unit> ResetNotifyer) CreateIsModifiedProperty(
params IReactiveProperty[] properties)
{
var subject = new Subject<Unit>();
return (
properties.Select(x => x.PropertyChangedAsObservable().Select(_ => true)).Append(subject.Select(_ => false))
.Merge()
.ToReadOnlyReactivePropertySlim(false),
subject
);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment