Skip to content

Instantly share code, notes, and snippets.

@spixy
Last active May 14, 2019 21:03
Show Gist options
  • Save spixy/e51937de63d1a6fde7d01a7043e93d8f to your computer and use it in GitHub Desktop.
Save spixy/e51937de63d1a6fde7d01a7043e93d8f to your computer and use it in GitHub Desktop.
public class Undo : IDisposable
{
private readonly Action _undoFunc;
private static Action CreateUndoFunc<TResult>(object obj, MemberInfo memberInfo, TResult newValue)
{
TResult oldValue;
switch (memberInfo)
{
case FieldInfo fieldInfo:
oldValue = (TResult)fieldInfo.GetValue(obj);
fieldInfo.SetValue(obj, newValue);
return () => { fieldInfo.SetValue(obj, oldValue); };
case PropertyInfo propertyInfo:
oldValue = (TResult)propertyInfo.GetMethod.Invoke(obj, Array.Empty<object>());
propertyInfo.SetMethod.Invoke(obj, new object[] { newValue });
return () => { propertyInfo.SetMethod.Invoke(obj, new object[] { oldValue }); };
default:
throw new Exception("Only property and field expressions are supported");
}
}
/// <summary>
/// Create Undo for static object
/// </summary>
public static Undo Create<TResult>(Expression<Func<TResult>> propertyFunc, TResult newValue)
{
MemberInfo memberInfo = (propertyFunc.Body as MemberExpression)?.Member;
Action undoFunc = CreateUndoFunc(null, memberInfo, newValue);
return new Undo(undoFunc);
}
/// <summary>
/// Create Undo for instance object
/// </summary>
public static Undo Create<T, TResult>(T obj, Expression<Func<T, TResult>> propertyFunc, TResult newValue)
{
MemberInfo memberInfo = (propertyFunc.Body as MemberExpression)?.Member;
Action undoFunc = CreateUndoFunc(obj, memberInfo, newValue);
return new Undo(undoFunc);
}
public Undo(Action undoFunc)
{
_undoFunc = undoFunc;
}
public void Dispose()
{
_undoFunc();
}
}
@spixy
Copy link
Author

spixy commented May 14, 2019

Example:

Console.WriteLine(Console.ForegroundColor); // red
using (Undo.Create(() => Console.ForegroundColor, ConsoleColor.Blue))
{
    Console.WriteLine(Console.ForegroundColor); // blue
}
Console.WriteLine(Console.ForegroundColor); // red

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment