Files

86 lines
2.4 KiB
C#
Raw Permalink Normal View History

using CommunityToolkit.Mvvm.ComponentModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace Cowain.Base.UndoRedo;
[Flags]
public enum PropertyFlags
{
Disable = 0,
Enable = 1
}
public abstract class Undoable : ObservableObject
{
private readonly HashSet<string> _trackedProperties = new HashSet<string>();
public IActionsHistory History { get; }
private void RecordHistory<TPropType>(string propName, TPropType previous, TPropType current)
{
if (_trackedProperties.Contains(propName))
{
var prop = PropertyCache.Get(GetType(), propName);
History.Record(() => prop.SetValue(this, current), () => prop.SetValue(this, previous), propName);
}
}
protected void RecordProperty(string propName, PropertyFlags flags = PropertyFlags.Enable)
{
if (flags == PropertyFlags.Disable)
{
_trackedProperties.Remove(propName);
}
else if (flags.HasFlag(PropertyFlags.Enable))
{
_trackedProperties.Add(propName);
}
}
protected void RecordProperty<TType>(Expression<Func<TType, object?>> selector, PropertyFlags flags = PropertyFlags.Enable)
{
if (!RuntimeFeature.IsDynamicCodeSupported)
return;
string name = GetPropertyName(selector);
RecordProperty(name, flags);
}
private static string GetPropertyName(Expression memberAccess)
=> memberAccess switch
{
LambdaExpression lambda => GetPropertyName(lambda.Body),
MemberExpression mbr => mbr.Member.Name,
UnaryExpression unary => GetPropertyName(unary.Operand),
_ => throw new Exception($"Member name could not be extracted from {memberAccess}.")
};
//protected override bool SetProperty<TPropType>(ref TPropType field, TPropType value, [CallerMemberName] string propertyName = "")
//{
// TPropType prev = field;
// if (base.SetProperty(ref field, value, propertyName))
// {
// RecordHistory(propertyName, prev, value);
// return true;
// }
// return false;
//}
public Undoable()
{
History = ActionsHistory.Global;
}
public Undoable(IActionsHistory history)
{
History = history;
}
}